美文网首页
Spring使用注解注册组件

Spring使用注解注册组件

作者: JBryan | 来源:发表于2020-01-18 11:47 被阅读0次
环境搭建

新建Maven项目spring-annotation-demo,添加Maven依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
</dependencies>
1.使用@Configuration和@Bean给容器中注册组件

新建bean包,Person类。三个属性:name,age,nickName。添加有参,无参,toString()方法。

package com.ljessie.bean;

import org.springframework.beans.factory.annotation.Value;

public class Person {

    private String name;
    private Integer age;    
    private String nickName;

    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nickName='" + nickName + '\'' +
                '}';
    }
    public Person() {
    }
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

新建config包,MainConfig类。在类名上添加@Configuration,告诉Spring,这是一个配置类;然后新建getPerson()方法,添加@Bean注解

package com.ljessie.config;

import com.ljessie.bean.Person;
import com.ljessie.service.BookService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

/**
 * 配置类等同于配置文件
 */
//告诉Spring,这是一个配置类
@Configuration
public class MainConfig {

    //给容器中注册一个Bean,类型为返回值的类型,
    @Bean(value = "Person")
    public Person getPerson(){
        return new Person("Bowen",19);
    }

}

在src/main/test下,新建测试类IOCTest,新建test01()方法,添加@Test注解。创建annotationConfigApplicationContext 对象加载MainConfig配置类,然后打印容器中定义的

package com.ljessie.test;

import com.ljessie.bean.Person;
import com.ljessie.config.MainConfig;
import com.ljessie.config.MainConfig2;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

public class IOCTest {
   
    @Test
    public void test01(){
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
        Person person = (Person) annotationConfigApplicationContext.getBean("Person");
        System.out.println(person);
    }

运行结果

一月 17, 2020 11:34:44 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Fri Jan 17 11:34:44 CST 2020]; root of context hierarchy
一月 17, 2020 11:34:44 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Fri Jan 17 11:34:44 CST 2020]; root of context hierarchy

一月 17, 2020 11:34:44 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3e3047e6: startup date [Fri Jan 17 11:34:44 CST 2020]; root of context hierarchy
一月 17, 2020 11:34:44 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
Person
Person{name='Bowen', age=19, nickName='null'}

2.@ComponentScan-自动扫描和指定扫描规则

新建component包,ComponentController添加@Controller,ComponentService添加@Service,ComponentDao添加@Repository。

package com.ljessie.component;

import org.springframework.stereotype.Controller;

@Controller
public class ComponentController {
}

package com.ljessie.component;

import org.springframework.stereotype.Service;

@Service
public class ComponentService {
}

package com.ljessie.component;

import org.springframework.stereotype.Repository;

@Repository
public class ComponentDao {
}

在MainConfig类上面添加@Component注解。@ComponentScan属性:Value,指定要扫描的包;

package com.ljessie.config;

import com.ljessie.bean.Person;
import com.ljessie.component.ComponentService;
import com.ljessie.controller.BookController;
import com.ljessie.service.BookService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

/**
 * 配置类等同于配置文件
 */
//告诉Spring,这是一个配置类
@Configuration
//value指定要扫描的包,
// excludeFilters排除要扫描的组件,
// includeFilters只扫描指定的组件,后面要加上useDefaultFilters
@ComponentScan(value = "com.ljessie.component")
public class MainConfig {

    //给容器中注册一个Bean,类型为返回值的类型,
    @Bean(value = "Person")
    public Person getPerson(){
        return new Person("Bowen",19);
    }

}

运行test01():componentController,componentDao,componentService注册进来了

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
componentController
componentDao
componentService
Person
Person{name='Bowen', age=19, nickName='null'}

includeFilters:只扫描指定的组件,后面要加上useDefaultFilters。可以指定组件的注解,类型和自定义过滤规则。

@ComponentScan(value = "com.ljessie.component"
,includeFilters = {
            //指定组件的注解
            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
            //指定组件的类型
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = ComponentService.class),
//            自定义过滤器
//            @ComponentScan.Filter(type = FilterType.CUSTOM,classes = CustomFilter.class)
}, useDefaultFilters = false
)
public class MainConfig {

    //给容器中注册一个Bean,类型为返回值的类型,
    @Bean(value = "Person")
    public Person getPerson(){
        return new Person("Bowen",19);
    }

}

运行test01():只注册了componentController和componentService,componentDao并没有被注册进来。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
componentController
componentService
Person
Person{name='Bowen', age=19, nickName='null'}

CustomFilter自定义过滤规则,如果组件中包含Controller,则注册。

package com.ljessie.component;

import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class CustomFilter implements TypeFilter {
    /**
     *
     * @param metadataReader 读取到的正在扫描类的信息
     * @param metadataReaderFactory 可以获取到的其他类的信息
     * @return
     * @throws IOException
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

        //获取当前类的注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

        //获取当前类的类型信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String className = classMetadata.getClassName();
        System.out.println("-------->"+className);

        //获取当前类的资源信息(路径等)
       metadataReader.getResource();

       if(className.contains("Controller")){
           return true;
       }
        return false;
    }
}

注掉includeFilters其他指定。

@ComponentScan(value = "com.ljessie.component"
//        , excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}
        ,includeFilters = {
            //指定组件的注解
//            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
            //指定组件的类型
//            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = ComponentService.class),
//            自定义过滤器
            @ComponentScan.Filter(type = FilterType.CUSTOM,classes = CustomFilter.class)
}, useDefaultFilters = false
)
public class MainConfig {
//省略其他代码
}

运行test01():只有componentController被注册进来了

一月 18, 2020 11:27:14 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@475e586c: startup date [Sat Jan 18 11:27:14 CST 2020]; root of context hierarchy
-------->com.ljessie.component.ComponentController
-------->com.ljessie.component.ComponentDao
-------->com.ljessie.component.ComponentService
-------->com.ljessie.component.CustomFilter
一月 18, 2020 11:27:14 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
componentController
Person
Person{name='Bowen', age=19, nickName='null'}

excludeFilters:排除要扫描的组件

@ComponentScan(value = "com.ljessie.component"
        , excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}
)
public class MainConfig {
//省略其他代码
}

运行test01():只有componentDao被注册进来了,排除了componentController和componentService。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
componentDao
Person
Person{name='Bowen', age=19, nickName='null'}
3.@Scope调整作用域

"singleton"; 单例,也是默认值。IOC容器启动会调用方法,创建对象到容器中,以后每次获取,从容器中拿。
"prototype"; 多实例。IOC容器启动,并不会调用方法,创建对象;而是每次获取的时候,才会调用方法,创建对象。
新建MainConfig2

package com.ljessie.config;

import com.ljessie.bean.Color;
import com.ljessie.bean.ColorFactoryBean;
import com.ljessie.bean.Person;
import com.ljessie.bean.Red;
import com.ljessie.condition.LinuxCondition;
import com.ljessie.condition.MyImportBeanDefinitionRegistrar;
import com.ljessie.condition.MyImportSelector;
import com.ljessie.condition.WindowsCondition;
import org.springframework.context.annotation.*;

@Configuration
public class MainConfig2 {


    /**
     * @Scope:调整作用域
     * String SCOPE_SINGLETON = "singleton"; 单例,也是默认值。IOC容器启动会调用方法,创建对象到容器中,以后每次获取,从容器中拿
     * String SCOPE_PROTOTYPE = "prototype"; 多实例。IOC容器启动,并不会调用方法,创建对象;而是每次获取的时候,才会调用方法,创建对象。
     * @return
     */
    @Scope("prototype")
    @Bean("zhangsan")
    public Person person(){
        System.out.println("给容器中添加person....");
        return new Person("zhangsan",25);
    }
}

在IOCTest里面新建test02()方法

 @Test
    public void test02(){
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
        System.out.println("容器创建完成");
        Person person1 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
        Person person2 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
        System.out.println(person1 == person2);
    }

运行结果:先创建容器,然后调用annotationConfigApplicationContext.getBean()方法时,才会创建Person实例,而且创建的两个实例不是同一对象。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
zhangsan
容器创建完成
给容器中添加person....
给容器中添加person....
false
4.@Lazy懒加载

单实例bean:默认容器启动时,创建对象;懒加载,在第一次获取对象的时候,创建对象,并进行初始化。
MainConfig2里面person()方法去掉@Scope,添加@Lazy

    @Lazy
    @Bean("zhangsan")
    public Person person(){
        System.out.println("给容器中添加person....");
        return new Person("zhangsan",25);
    }

运行test02()

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
zhangsan
容器创建完成
给容器中添加person....
true
5.@Conditional按照条件注册Bean

新建Condition包,ZhangsanCondition类,实现Condition接口。matches()方法实现匹配逻辑:如果容器中已经包含id为"zhangsan"的bean,则注册当前bean;否则不注册。

package com.ljessie.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class ZhangsanCondition implements Condition {
    /**
     *
     * @param context 判断条件使用的上下文环境
     * @param metadata 当前注释信息
     * @return
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取到IOC使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //获取到类加载器
        ClassLoader classLoader = context.getClassLoader();
        //获取到环境
        Environment environment = context.getEnvironment();
        //获取到bean的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        //可以判断容器中的注册情况,也可以给容器中注册Bean
        //如果容器中包含"zhangsan",则注册;如果不包含,则不注册
        boolean containsZhangsan = registry.containsBeanDefinition("zhangsan");
        if(containsZhangsan){
            return true;
        }

//        String property = environment.getProperty("os.name");
//        if(property.contains("linux")){
//            return true;
//        }

        return false;
    }
}

MainConfig2里面添加person02()方法

    @Conditional({ZhangsanCondition.class})
    @Bean("zhangwu")
    public Person person02(){
        return new Person("zhangwu",27);
    }

运行test02()

@Test
    public void test02(){
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
        System.out.println("容器创建完成");
//        Person person1 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
//        Person person2 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
//        System.out.println(person1 == person2);
    }

运行结果,"zhangsan"和"zhangwu"都已经被注册到容器中了。

给容器中添加person....
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
zhangsan
zhangwu
容器创建完成

此时注掉MainConfig2里面的person()方法,重新运行test02()。此时"zhangsan"和"zhangwu"都没有被注册到容器中。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
容器创建完成
6.使用@Import给容器中注册组件

在bean包下,新建Color,Red

package com.ljessie.bean;

public class Color {
}
package com.ljessie.bean;

public class Color {
}

在MainConfig2类上面添加@Import

@Import({Color.class, Red.class})
public class MainConfig2 {
//省略其他代码
}

IOCTest里面新建testImport()方法

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);

    @Test
    public void testImport(){
        printBeans(annotationConfigApplicationContext);
        //工厂bean获取的是:getObject()创建的对象
        //Object colorFactoryBean = annotationConfigApplicationContext.getBean("colorFactoryBean");
        //System.out.println(colorFactoryBean.getClass());

    }

    public void printBeans(AnnotationConfigApplicationContext annotationConfigApplicationContext){
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
    }

运行testImport():Color和Red都已经注册到容器中了。

org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 10:49:33 CST 2020]; root of context hierarchy

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.ljessie.bean.Color
com.ljessie.bean.Red

使用ImportSelector注册组件
新建Blue,Yellow类

package com.ljessie.bean;

public class Blue {
}
package com.ljessie.bean;

public class Yellow {
}

新建MyImportSelector,实现ImportSelector方法

package com.ljessie.condition;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * 自定义逻辑,返回需要导入的组件
 */
public class MyImportSelector implements ImportSelector {
    /**
     *
     * @param importingClassMetadata 当前标注@Import注解的类的所有注册信息
     * @return 返回值就是导入容器中的组件的全类名,不要返回null
     */
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[]{"com.ljessie.bean.Blue","com.ljessie.bean.Yellow"};
    }
}

MainConfig2里面@Import添加MyImportSelector .class

@Import({Color.class, Red.class, MyImportSelector.class})
public class MainConfig2 {
//省略其他代码
}

运行testImport():Blue和Yellow也注册进来了

org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 10:56:22 CST 2020]; root of context hierarchy

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.ljessie.bean.Color
com.ljessie.bean.Red
com.ljessie.bean.Blue
com.ljessie.bean.Yellow

使用ImportBeanDefinitionRegistrar注册组件
新建RainBow类

package com.ljessie.bean;

public class RainBow {
}

新建MyImportBeanDefinitionRegistrar,实现ImportBeanDefinitionRegistrar接口:如果容器中包含Red,则注册RainBow

package com.ljessie.condition;

import com.ljessie.bean.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     *
     * @param importingClassMetadata:当前类的注册信息
     * @param registry:BeanDefinition的注册类,所有要添加到容器中的bean
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean red = registry.containsBeanDefinition("com.ljessie.bean.Red");
        if(red){
            //指定Bean的定义信息
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个Bean
            registry.registerBeanDefinition("rainBow", rootBeanDefinition);
        }
    }
}

MainConfig2类上面,@Import注解添加MyImportBeanDefinitionRegistrar.class

@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
//省略其他代码
}

运行testImport()方法:rainBow注册进来了。

org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 11:02:51 CST 2020]; root of context hierarchy

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.ljessie.bean.Color
com.ljessie.bean.Red
com.ljessie.bean.Blue
com.ljessie.bean.Yellow
rainBow
7.使用FactoryBean给容器中注册组件

新建ColorFactoryBean,实现FactoryBean接口

package com.ljessie.bean;

import org.springframework.beans.factory.FactoryBean;

/**
 * 创建一个Spring提供的工厂Bean
 */
public class ColorFactoryBean implements FactoryBean<Color> {
    /**
     *
     * @return Color对象,添加到容器中
     * @throws Exception
     */
    public Color getObject() throws Exception {
        System.out.println("ColorFactoryBean----->getObject()");
        return new Color();
    }

    public Class<?> getObjectType() {
        return Color.class;
    }

    public boolean isSingleton() {
        return true;
    }
}

在MainConfig2里面添加方法

@Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }

修改testImport():

@Test
    public void testImport(){
        printBeans(annotationConfigApplicationContext);
        //工厂bean获取的是:getObject()创建的对象
        Object colorFactoryBean = annotationConfigApplicationContext.getBean("colorFactoryBean");
        System.out.println(colorFactoryBean.getClass());

    }

    public void printBeans(AnnotationConfigApplicationContext annotationConfigApplicationContext){
        String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
    }

运行testImport(),拿到的colorFactoryBean实际是,getObject()方法里返回的Color类型。

org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 11:09:11 CST 2020]; root of context hierarchy

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.ljessie.bean.Color
com.ljessie.bean.Red
com.ljessie.bean.Blue
com.ljessie.bean.Yellow
colorFactoryBean
rainBow
ColorFactoryBean----->getObject()
class com.ljessie.bean.Color
组件注册总结

1.包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
2.@Bean[导入的第三方包]
3.@Import
1).@Import(要导入容器的组件)
2).ImportSelector:返回需要导入的组件的全类名数组
3).ImportBeanDefinitionRegistrar:手动注册bean到容器中
4.使用Spring提供的FactoryBean(工厂Bean)
1).默认获取到的是工厂Bean调用getObject()创建的对象
2).要获取工厂Bean本身,需要给id前面加一个&

相关文章

网友评论

      本文标题:Spring使用注解注册组件

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