美文网首页
Spring学习笔记 | 详解bean的配置(三):继承配置 |

Spring学习笔记 | 详解bean的配置(三):继承配置 |

作者: 一颗白菜_ | 来源:发表于2019-10-14 23:39 被阅读0次

    继承Bean配置

    • Spring允许继承bean的配置,被继承的bean称为父bean,继承这个父bean的bean称为子bean。通过设置parent来实现继承。
    • 子bean从父bean中继承配置,包括bean的属性配置
    • 子bean可以覆盖从父bean继承过来的配置。
    • 父bean可以作为配置模板,也可以作为bean实例,若只想把父bean作为模板,可以设置<bean>abstract属性为true这样Spring将不会实例化这个bean。
    • 并不是<bean>元素里的所有属性都会被继承,比如:autowire,abstract等。
    • 可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的属性配置,但是此时abstract必须设为true

    我们此时有两个 address类型的bean,如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="address" class="com.spring.autowire.Address" p:city="BeiJing" p:street="WuDaoKou"></bean>
        <bean id="address1" class="com.spring.autowire.Address" p:city="BeiJing" p:street="DaZhongSi"></bean>
    
    </beans>
    

    两个bean之间有很多相同的属性比如classcity,因此我们如果让第二个bean继承第一个bean,再把不同的属性加以覆盖,就可以使该配置文件简易许多:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="address" class="com.spring.autowire.Address" p:city="BeiJing" p:street="WuDaoKou"></bean>
        <bean id="address1" p:street="DaZhongSi" parent="address"></bean>
    
    </beans>
    

    如果想把第一个bean不被实例化,只作为其他bean的模板bean,则可以将其设置为抽象bean:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="address"  class="com.spring.autowire.Address" p:city="BeiJing" p:street="WuDaoKou" abstract="true"></bean>
        <bean id="address1"  p:street="DaZhongSi" parent="address"></bean>
    
    </beans>
    

    此时要切记抽象bean不能被实例化。


    依赖bean配置

    • Spring允许用户通过depend-on属性设定bean前置依赖的bean,前置依赖的bean会在本bean实例化之前创建好。
    • 如果前置依赖于多个bean,则可以通过逗号,空格等方式配置bean的名称。

    bean的作用域

    使用<bean>scope属性来配置bean的作用域:

    • singleton:默认值。在IOC容器初始化时创建bean实例,在整个容器的生命周期内只创建这一个bean,是单例的
    • prototype:原型的。IOC容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回。

    例如:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="car" class="com.spring.autowire.Car" scope="prototype">
            <property name="brand" value="Audi"/>
            <property name="price" value="300000"/>
        </bean>
    </beans>
    

    使用外部属性文件

    在配置文件里配置bean时,有时需要在bean的配置里混入系统部署的细节信息(例如:文件路径,数据源配置信息等),而这些部署细节实际上需要和bean配置相分离。

    Spring提供了一个PropertyPlaceholderConfigurerBeanFactory后置处理器,这个处理器允许用户将bean配置的部分内容外移到属性文件中,可以在bean配置文件里使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量。

    Spring还允许在属性文件中使用${propName}以实现属性之间的相互引用。

    示例:
    如果我们不使用外部属性文件的话,在beans-properties.xml配置DataSource类型的一个bean如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="user" value="root"/>
            <property name="password" value="root"/>
            <property name="driverClass" value="com.mysql.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql:///my_test_mysql"/>
        </bean>
    
    </beans>
    

    这样也能配置,但是就显得不大灵活了,当我们需要更改这些数据库属性参数时还得进该配置文件来更改。

    如果我们使用外部资源文件来进行配置,步骤如下:
    我们定义一个外部的资源文件db.properties,里面存放数据库的属性配置:

    user=root
    password=root
    driverClass=com.mysql.jdbc.Driver
    jdbcUrl=jdbc:mysql:///my_test_mysql
    

    bean配置文件beans-properties.xml,里面配置了DataSource类型的bean:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <!--导入属性文件-->
        <context:property-placeholder location="classpath:db.properties"/>
        <!--配置bean-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="user" value="${user}"/>
            <property name="password" value="${password}"/>
            <property name="driverClass" value="${driverClass}"/>
            <property name="jdbcUrl" value="${jdbcUrl}"/>
        </bean>
    </beans>
    

    通过工厂方法配置bean

    静态工厂方法

    调用静态工厂方法创建bean是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节。

    要声明通过静态方法创建的bean,需要在bean的class属性里指定拥有该工厂的方法的类,同时在配置文件中进行配置,具体属性如下:

    • class属性:指向静态工厂方法的全类名
    • factory-method:指向静态工厂方法的名字
    • construtor-arg:如果工厂方法需要传入参数,则使用construtor-arg来配置参数

    示例:

    • 创建bean类:
    package com.spring.factory;
    
    public class Car {
        private String brand;
        private double price;
    
        public Car(String brand, double price) {
            this.brand = brand;
            this.price = price;
        }
    
        public Car() {
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "brand='" + brand + '\'' +
                    ", price=" + price +
                    '}';
        }
    }
    
    
    • 创建静态工厂类:
    package com.spring.factory;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 静态工厂方法:直接调用某一个类的静态方法就可以返回bean实例
     */
    public class StaticCarFactory {
        private static Map<String,Car> cars = new HashMap <String, Car>();
    
        static {
            cars.put("audi",new Car("audi",100000));
            cars.put("ford",new Car("ford",200000));
        }
    
        //静态工厂方法
        public static Car getCar(String carName) {
            return cars.get(carName);
        }
    }
    
    

    beans-factory.xml配置文件中进行配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- 通过静态工厂方法配置bean,注意不是配置静态工厂方法实例,而是配置bean实例-->
        <bean id="car1" class="com.spring.factory.StaticCarFactory" factory-method="getCar">
            <constructor-arg value="audi"></constructor-arg>
        </bean>
    </beans>
    

    实例工厂方法

    将对象的创建过程封装到另外一个对象实例的方法里,当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节。

    要声明通过实例工厂方法创建的bean,需要如下步骤:

    • factory-bean:指定拥有该工厂方法的bean
    • factory-method:指向静态工厂方法的名字
    • constructor-arg:如果工厂方法需要传入参数,则使用construtor-arg来配置参数

    实例:
    bean类我们使用静态工厂方法时创建的bean类,因此我们不需要创建新的bean类。

    • 创建实例工厂方法类:
    package com.spring.factory;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 实例工厂方法:实例工厂的方法,即先要创建工厂本身,再调用工厂的实例工厂来返回bean的实例
     *
     */
    public class InstanceCarFactory {
        private Map<String,Car> cars = null;
    
        public InstanceCarFactory(){
            cars = new HashMap <String, Car>();
            cars.put("audi",new Car("audi",1000000));
            cars.put("ford",new Car("ford",2000000));
    
        }
    
        public Car getCar(String brand){
            return cars.get(brand);
        }
    }
    
    
    • beans-factory.xml配置文件中进行配置如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- 通过静态工厂方法配置bean,注意不是配置静态工厂方法实例,而是配置bean实例-->
        <bean id="car1" class="com.spring.factory.StaticCarFactory" factory-method="getCar">
            <constructor-arg value="audi"></constructor-arg>
        </bean>
    
        <!-- 配置工厂的实例-->
        <bean id="carFactory" class="com.spring.factory.InstanceCarFactory"></bean>
    
        <!-- 通过实例工厂来配置bean-->
        <bean id="car2" factory-bean="carFactory" factory-method="getCar">
            <constructor-arg value="ford"></constructor-arg>
        </bean>
    </beans>
    

    通过FactoryBean配置bean

    通过factoryBean来配置bean的实例
    class:指向FactoryBean的全类名
    property:配置FactoryBean的属性
    但实际返回的实例却是FactoryBean的getObject()返回的实例。

    package com.spring.factoryBean;
    
    import org.springframework.beans.factory.FactoryBean;
    
    public class CarFactoryBean implements FactoryBean<Car> {
    
        private String brand;
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        //返回bean的对象
        @Override
        public Car getObject() throws Exception {
            return new Car(brand,10000);
        }
    
        //返回bean的类型
        @Override
        public Class < ? > getObjectType() {
            return Car.class;
        }
    
        //返回是否是单实例
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--
            通过factoryBean来配置bean的实例
            class:指向FactoryBean的全类名
            property:配置FactoryBean的属性
            但实际返回的实例却是FactoryBean的getObject()返回的实例。
        -->
        <bean id="car" class="com.spring.factoryBean.CarFactoryBean">
            <property name="brand" value="BMW"></property>
        </bean>
    </beans>
    

    通过注解配置bean(一):基于注解配置bean

    我们首先要先引入一个扫描组件的概念。

    在classpath中扫描组件

    Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件,我们称为组件扫描。

    特定组件包括:

    • @Component:基本注解,标识了一个受Spring管理的组件
    • @Respository:标识持久层组件
    • @Service:标识服务层(业务层)组件
    • @Controller:标识表现层组件

    对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称

    当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>

    • base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。
    • 当需要扫描多个包时,可以使用逗号分隔
    • 如果仅仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例:
    <context:component-scan 
        base-package="com.spring.annotation" 
        resource-pattern="repository/*.class"></context:component-scan>
    
    • <context:include-filter>子节点表示要包含的目标类,需要与context:component-scan节点中use-default-filters配合使用(设置为false
    • <context:exclude-filter>子节点表示要排除在外的目标类
    • <context:component-scan>下可以拥有若干个<context:include-filter><context:exclude-filter>字节。
    • <context:include-filter><context:exclude-filter>子节点支持多种类型的过滤表达式,在此介绍两种:
    类别 示例 说明
    annotation com.cerr.XxxAcnotaion 所有标注了XXXAnnotation的类。该类型采用目标类是否标注了某个注解进行过滤
    assinable com.cerr.XxxService 所有继承或扩展XXXService的类。该类型采用目标类是否继承或扩展某个特定类进行过滤。

    配置示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <!-- 指定SpringIOC容器扫描的包 -->
        <!-- 可以通过resource-pattern指定扫描的资源 -->
        <!--
        <context:component-scan base-package="com.spring.annotation" resource-pattern="repository/*.class"></context:component-scan>
        -->
        
    
    
        <context:component-scan base-package="com.spring.annotation" use-default-filters="false">
            <!-- context:exclude-filter子节点指定排除哪些指定表达式的组件-->
            <!--
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
            -->
    
            <!-- context:include-filter子节点指定包含哪些指定表达式的组件,需要与context:component-scan节点中use-default-filters配合使用-->
            <!--
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
            -->
            <!--
            <context:exclude-filter type="assignable" expression="com.spring.annotation.repository.UserRepository"/>
            -->
            <!--
            <context:include-filter type="assignable" expression="com.spring.annotation.repository.UserRepository"/>
            -->
        </context:component-scan>
    </beans>
    

    通过注解配置bean(二)

    如果多个bean之间有关联,比如我们定义一个接口UserRepository如下:

    package com.spring.annotation.repository;
    
    public interface UserRepository {
        void save();
    }
    

    其有一个实现类UserRepositoryImpl

    package com.spring.annotation.repository;
    
    import org.springframework.stereotype.Repository;
    
    @Repository("userRepository")
    public class UserRepositoryImpl implements UserRepository{
    
        @Override
        public void save() {
            System.out.println("UserRepository Save..");
        }
    }
    

    有一个UserService类有该接口类型的成员变量:

    package com.spring.annotation.service;
    
    import com.spring.annotation.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        
        private UserRepository userRepository;
        public void add(){
            System.out.println("UserService add..");
            userRepository.save();
        }
    }
    

    然后还有一个UserController类也有一个UserService类型的变量。

    package com.spring.annotation.controller;
    
    import com.spring.annotation.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController {
    
        private UserService userService;
    
        public void execute(){
    
            System.out.println("UserController execute...");
            userService.add();
        }
    }
    
    

    这三个类之间就存在了关联关系,然后我们在beans-annotation.xml文件中配置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <context:component-scan base-package="com.spring.annotation"></context:component-scan>
    </beans>
    

    我们在主方法中获取UserController的bean对象并且调用其execute():

    package com.spring.annotation;
    
    import com.spring.annotation.controller.UserController;
    import com.spring.annotation.repository.UserRepository;
    import com.spring.annotation.repository.UserRepositoryImpl;
    import com.spring.annotation.service.UserService;
    import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
            System.out.println(userController);
            userController.execute();
        }
    }
    
    

    运行代码会发现出现异常,因为UserController的bean对象的方法中有使用到UserService的bean对象,而在UserService对象的方法中也使用到了UserRepository接口,而此时他们都未装配,因此就出现了异常。

    对于上述的异常,我们可以使用@Autowired进行自动装配,即在要使用到的成员类进行注解或者注解其setter方法也可。

    <context:component-scan>元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired@Resource@Inject注解的属性。

    使用@Autowired自动装配bean

    @Autowired注解可以自动装配具有兼容类型的单个bean属性:

    • 构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Autowired注解
    • 默认情况下,所有使用@Autowired注解的属性都需要被设置,当Spring找不到匹配的bean装配属性时,会抛出异常,即我们要在配置文件中配置它,**若某一属性允许不被设置,可以设置@Autowired注解的request属性为false,例如@Autowired(request=false)
      对于上面错误的例子,我们对其加了注解后的代码如下:
    package com.spring.annotation.controller;
    
    import com.spring.annotation.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController {
        //加了注解
        @Autowired
        private UserService userService;
    
        public void execute(){
    
            System.out.println("UserController execute...");
            userService.add();
        }
    }
    
    package com.spring.annotation.service;
    
    import com.spring.annotation.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        //加了注解
        @Autowired
        private UserRepository userRepository;
        public void add(){
            System.out.println("UserService add..");
            userRepository.save();
        }
    }
    
    • 默认情况下,当IOC容器里存在多个类型兼容的bean时,通过类型的自动装配将无法工作,此时可以在@Qualifier注解里提供bean的名称,Spring允许对方法的入参标注@Qualifiter已指定注入的bean的名称。
      例如我们此时多定义一个UserRepository的实现类UserJdbcRepository
    package com.spring.annotation.repository;
    import org.springframework.stereotype.Repository;
    @Repository
    public class UserJdbcRepository implements UserRepository{
        @Override
        public void save() {
    
        }
    }
    
    

    我们再把UserRepositoryImpl中的@Repository("userRepository")的命名去掉,变为@Repository。此时我们有了两个UserRepository接口的实现类,而此时通过@AutoWired注解的是UserRepository接口,因此允许代码会出现异常。

    我们此时有两种解决方法,可以在UserRepositoryImpl中的@Repository中加上我们注解的userRepository。另一种方法使用@Qualifiter注解提供bean的名称。

    注解后的UserService如下所示:

    package com.spring.annotation.service;
    
    import com.spring.annotation.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        @Autowired
        @Qualifier("userRepositoryImpl")
        private UserRepository userRepository;
        public void add(){
            System.out.println("UserService add..");
            userRepository.save();
        }
    }
    
    • @Autowired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的bean进行自动装配。
    • @Autowired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的bean。
    • @Autowired注解用在java.util.Map上时,若该Map的键值是String,那么Spring将自动装配与之Map值类型兼容的bean,此时bean的名称作为键值。

    使用@Resource或@Inject自动装配bean

    这两者与@Autowired注解的功能类似。

    @Resource注解要求提供一个bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为bean的名称

    @Inject@Autowired注解一样也是按类型匹配注入的bean,但没有required属性。我们建议使用@Autowired注解。


    泛型依赖注入(Spring4的新特性)

    Spring 4中可以为子类注入子类对应的泛型类型的成员变量的引用。

    即父类泛型类型之间建立了关联关系,而对应的子类之间没有建立关联关系,Spring会为其对应的子类建立关联关系。

    我们以下图所示的uml图来举例:


    类图

    我们现在有两个泛型父类BaseService<T>BaseRepository< T >BaseRepository<T>BaseService<T>的成员变量,代码如下:

    package com.spring.generic.di;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class BaseService<T> {
    
        @Autowired
        protected  BaseRepository<T> repository;
    
        public void add(){
            System.out.println("add");
            System.out.println(repository);
        }
    }
    
    package com.spring.generic.di;
    
    public class BaseRepository< T > {
    }
    

    有一个User类如下:

    package com.spring.generic.di;
    
    public class User {
    }
    

    上述两个泛型基类的两个子类UserServiceUserRepository代码如下(这两个子类之间没有建立关联关系):

    package com.spring.generic.di;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService extends BaseService<User> {
    }
    
    package com.spring.generic.di;
    
    import org.springframework.stereotype.Repository;
    
    @Repository
    public class UserRepository extends BaseRepository<User> {
    }
    

    在配置文件beans-generic-di.xml中配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="com.spring.generic.di"/>
    </beans>
    

    主方法:

    package com.spring.generic.di;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-generic-di.xml");
    
            UserService userService = (UserService) ctx.getBean("userService");
            userService.add();
        }
    }
    

    运行后控制台打印如下:

    add
    com.spring.generic.di.UserRepository@6d3af739
    

    我们发现其子类之间也自动的建立了关联关系,自动初始化了UserRepository类。

    相关文章

      网友评论

          本文标题:Spring学习笔记 | 详解bean的配置(三):继承配置 |

          本文链接:https://www.haomeiwen.com/subject/dlswpctx.html