Spring注解驱动之组件注册

spring注解驱动

1. 组件注册—@Configuration与@Bean

1.1 基于xml配置文件注入bean

准备工作:使用IDEA创建maven工程spring_annotation,pom.xml中引入以下依赖:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
</dependencies>

java目录下新建包名为com.trisirt.spring.annotation.bean,包内新建一个Person类:

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

resources目录下新建beans.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 id="person" class="com.trisirt.spring.annotation.bean.Person">
        <property name="age" value="18"></property>
        <property name="name" value="Tom"></property>
    </bean>
</beans>

com.trisirt.spring.annotation包内新建主测试类MainTest.calss

public class MainTest {

    public static void main(String[] args) {
        // 基于xml注入JavaBean
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
    }
}

启动主程序测试注入结果:
基于xml方式注入bean测试

1.2 基于注解方式注入bean

com.trisirt.spring.annotation.config包下新建配置类MainConfig.class

/**
 * 使用配置类代替配置文件,实现完全注解开发
 * 配置类本身也是一个组件
 */
@Configuration // 告诉spring这是一个配置类
public class MainConfig {
    // 给容器中注册一个bean,类型为返回值的类型,id默认是用方法名作为id
    @Bean
    public Person person() {
        return new Person("Jack", 20);
    }
}

修改MainTest.calss为使用注解注入的方式:

public class MainTest {

    public static void main(String[] args) {
        // 基于注解注入JavaBean
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person = applicationContext.getBean(Person.class);
        System.out.println(person);
    }
}

测试结果如下:
基于注解注入bean测试
实现注解注入后可以使用getBeanNamesForType()方法获取Person类型的组件在IOC容器中的名字:

// MainTest.class中加入以下代码段
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
    System.out.println(name); // 结果为:person
}

修改MainConfig.class中方法名为person01,可以看到容器中名字也对应被修改为person01

@Configuration
public class MainConfig {
    @Bean
    public Person person01() { // MainTest打印结果为:person01
        return new Person("Jack", 20);
    }
}

也可通过@Bean注解中的name或value属性指定容器中Person类的名字:

@Configuration
public class MainConfig {
    @Bean(name="person_jack") // MainTest打印结果为:person_jack
    public Person person01() {
        return new Person("Jack", 20);
    }
}

2. 组件注册—@ComponenScan

2.1 基于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 http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component -->
     <context:component-scan base-package="com.trisirt" use-default-filters="false"></context:component-scan> 
</beans>
2.1 基于注解方式包扫描定义

准备工作:在com.trisirt.spring.annotation包下分别创建controller.BookController.classservice.BookServicedao.BookDao,仅作演示,不涉及具体业务逻辑:

@Controller
public class BookController {
}
@Service
public class BookService {
}
@Repository
public class BookDao {
}

MainConfig.class中使用@ComponentScan注解定义扫描规则:

@Configuration // 告诉spring这是一个配置类
@ComponentScan(value = "com.trisirt")
// @ComponentScan value:指定要扫描的包
public class MainConfig {
    // 给容器中注册一个bean,类型为返回值的类型,id默认是用方法名作为id
    @Bean(name="person_jack")
    public Person person01() {
        return new Person("Jack", 20);
    }
}

新建测试类进行测试,打印容器中所有的组件名称:

public class IOCTest {
    @SuppressWarnings("resource")
    @Test
    public void test01() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] names = applicationContext.getBeanDefinitionNames();
        for(String name : names) {
            System.out.println(name);
        }
    }
}

打印结果中除了IOC基本容器之外还有我们自己定义的mainConfig、bookController、bookDao、bookService、person_jack等bean
基于注解的包扫描规则定义测试结果
@ComponentScan还可以使用excludeFiltersincludeFilters定义排除或包含规则:

@Configuration // 告诉spring这是一个配置类
// @ComponentScan
// value:指定要扫描的包
// excludeFilters = Filter[]:指定扫描的时候按照什么规则排除哪些组件
// includeFilters = Filter[]:指定扫描的时候只需要包含哪些组件
@ComponentScan(value = "com.trisirt", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})
public class MainConfig {
    // 给容器中注册一个bean,类型为返回值的类型,id默认是用方法名作为id
    @Bean(name="person_jack")
    public Person person01() {
        return new Person("Jack", 20);
    }
}

可以看到加上以上excludeFilters之后,打印结果中就没有bookControllerbookService这两个bean了。
对于includeFilters,需要注意只有加上useDefaultFilters = false规则才会生效,因为spring底层默认includeFilters包含所有组件

@Configuration // 告诉spring这是一个配置类
// @ComponentScan
// value:指定要扫描的包
// excludeFilters = Filter[]:指定扫描的时候按照什么规则排除哪些组件
// includeFilters = Filter[]:指定扫描的时候只需要包含哪些组件
@ComponentScan(value = "com.trisirt", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})},
        useDefaultFilters = false
        )
public class MainConfig {
    // 给容器中注册一个bean,类型为返回值的类型,id默认是用方法名作为id
    @Bean(name="person_jack")
    public Person person01() {
        return new Person("Jack", 20);
    }
}

使用以上注解打印结果为mainConfig、bookController、person_jack,不包含bookControllerbookService这两个bean。
同一个配置类中,可以多次使用@ComponentScan注解来定义扫描规则
另外,早期版本的jdk还提供@ComponentScans注解,可以实现一次定义多个@ComponentScan规则:

@ComponentScans(
        value = {
        @ComponentScan(value = "com.trisirt", includeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})},
                useDefaultFilters = false)
})

3. 组件注册—自定义FilterType指定过滤规则

前面的@ComponentScan中使用了@ComponentScan.Filter注解,其中属性type有以下五种:

  • FilterType.ANNOTATION:按照注解
  • FilterType.ASSIGNABLE_TYPE:按照给定的类型
  • FilterType.ASPECTJ:按照AspectJ规则
  • FilterType.REGEX:按照正则
  • FilterType.CUSTOM:按照自定义
    自定义过滤器规则:实现TypeFilter接口,重写match()方法,定义过滤规则:
public class MyTypeFilter implements TypeFilter {

    /**
     *
     * @param metadataReader 读取到的当前正在扫描的类信息
     * @param metadataReaderFactory 可以获取到其他任何类信息
     * @return
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类注释的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫描的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();
        
        // 打印类名信息
        String className = classMetadata.getClassName();
        System.out.println("--->" + className);
		
		// 设置过滤规则为类名中包含"er"的类
        if(className.contains("er"))
            return true;
        return false;
    }

MainConfig中使用自定义过滤器

@Configuration // 告诉spring这是一个配置类
// @ComponentScan
// value:指定要扫描的包
// excludeFilters = Filter[]:指定扫描的时候按照什么规则排除哪些组件
// includeFilters = Filter[]:指定扫描的时候只需要包含哪些组件
@ComponentScan(value = "com.trisirt", includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})},
        useDefaultFilters = false)
public class MainConfig {
    // 给容器中注册一个bean,类型为返回值的类型,id默认是用方法名作为id
    @Bean(name="person_jack")
    public Person person01() {
        return new Person("Jack", 20);
    }
}

运行测试程序test01()结果如下:

--->com.trisirt.spring.annotation.bean.Person
--->com.trisirt.spring.annotation.config.MyTypeFilter
--->com.trisirt.spring.annotation.controller.BookController
--->com.trisirt.spring.annotation.dao.BookDao
--->com.trisirt.spring.annotation.MainTest
--->com.trisirt.spring.annotation.service.BookService
--->com.trisirt.spring.annotation.test.IOCTest
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
myTypeFilter
bookController
bookService
person_jack
组件注册–@Scope
@Configuration
public class MainConfig2 {

    // @Scope:调整作用域
    // prototype:多实例:IOC容器启动并不会去调用方法创建对象放到IOC容器中,每次获取的时候才会调用方法创建对象
    // singleton:単实例(默认的):IOC容器启动会调用方法创建对象放到容器中,以后每次获取就是直接从容器中拿
    // request:同一次请求创建一个实例
    // session:同一个session创建一个实例
    @Scope("prototype")
    @Bean("person")
    public Person person() {
        return new Person("张三", 25);
    }
}
组件注册–@Lazy
/*
懒加载:
	  単实例bean:默认在容器启动的时候创建对象
	  懒加载:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化
*/
@Configuration
public class MainConfig2 {
    @Lazy
    @Bean("person")
    public Person person() {
        System.out.println("给容器中添加person...");
        return new Person("张三", 25);
    }
}

测试类代码增加打印语句,观察输出显示容器创建和向容器添加Person的次序:

@Test
    public void test02() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);

        System.out.println("ioc容器创建完成...");
        Object bean1 = applicationContext.getBean("person");
        Object bean2 = applicationContext.getBean("person");
        System.out.println(bean1 == bean2);
    }

使用@lazy注解之后是懒加载模式,先创建容器,再注入person,打印结果如下:

ioc容器创建完成...
给容器中添加person...
true
组件注册–@Conditional

@Conditional可以放在方法或者类名上方,放在类名上方:类中组件统一设置。表示满足该条件时,这个类中配置的所有bean注册才能生效。

Mainconfig2类新增加两个组件(“bill"和"linus”)注册定义,使用@Conditional注解需要传入Condition[]数组作为条件,条件定义如下:

@Configuration
public class MainConfig2 {
    
    @Bean("person")
    public Person person() {
        //System.out.println("给容器中添加person...");
        return new Person("张三", 25);
    }

    /**
     * @Conditional({Condition}):按照一定条件进行判断,满足条件给容器中注册bean
     *
     * 需求:
     * 如果系统是windows,给容器中注册("bill")
     * 如果系统是linux,给容器中注册("linus")
     */
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 66);
    }

    @Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("Linus Torvalds", 52);
    }

}

com.trisirt.spring.annotation.condition包下新建两个类:WindowsConditionLinuxCondition,用于定义判断操作系统类型的条件

// 判断是否linux系统
public class LinuxCondition implements Condition {
    /**
     *
     * @param conditionContext 判断条件能使用的上下文环境
     * @param annotatedTypeMetadata 注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        // 判断是否linux系统
        // 1、能获取到ioc使用的beanfactory
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        // 2、获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        // 3、获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        // 4、获取bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();

        // 可以判断容器中bean注册情况,也可以给容器中注册bean
        boolean definition = registry.containsBeanDefinition("person");

        String OSName = environment.getProperty("os.name");
        if(OSName.contains("Linux")) {
            return true;
        }
        return false;
    }
}
// 判断是否windows操作系统
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String OSName = environment.getProperty("os.name");
        if(OSName.contains("Windows")) {
            return true;
        }
        return false;
    }
}

新建测试方法test03()

@Test
    public void test03() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);

        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        // 动态获取环境变量的值:Windows 10
        String OSName = environment.getProperty("os.name");
        System.out.println(OSName);

        String[] names = applicationContext.getBeanNamesForType(Person.class);
        for(String name : names) {
            System.out.println(name);
        }

        Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
        System.out.println(persons);
    }

由于当前系统为Win10,因此测试结果如下:

Windows 10
person
bill
{person=Person{name='张三', age=25}, bill=Person{name='Bill Gates', age=66}}

为了测试Linux系统的效果,可以在IDEA运行控制页面上选择Edit Configurations...,在虚拟机参数VM options一栏中输入:-Dos.name=Linux,再次运行即可得到如下结果:

Linux
person
linus
{person=Person{name='张三', age=25}, linus=Person{name='Linus Torvalds', age=52}}
组件注册–@Import

bean包下新建ClolorRed两个类,使用@Import可直接导入

@Configuration
// 导入组件,id默认是组件的全类名
@Import({Color.class, Red.class})
public class MainConfig2 {
    @Bean("person")
    public Person person() {
        return new Person("张三", 25);
    }
    
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 66);
    }

    @Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("Linus Torvalds", 52);
    }

    /**
     * 给容器中注册组件:
     * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
     * 2)、@Bean[导入第三方包里面的组件]
     * 3)、@Import[快速给容器中导入一个组件]
     *      1)、@Import(要导入到容器中的组件),容器中就会自动注册这个组件,id默认是全类名
     *      2)、@ImportSelector:返回需要到导入的组件的全类名数组
     *      3)、@ImportBeanDefinitionRegistrar:手动注册bean到容器中
     */

}
使用ImportSelector

bean包下新建BlueYellow两个类,在condition包下新建MyImportSelector类,返回要导入的组件的全类名数组

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

        // 方法不要返回null值
        //return new String[0];
        return new String[]{"com.trisirt.spring.annotation.bean.Blue", "com.trisirt.spring.annotation.bean.Yellow"};
    }
}

使用上面自定义的MyImportSelector.class作为@Import的参数

@Configuration
// 导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class})
public class MainConfig2 {
    @Bean("person")
    public Person person() {
        return new Person("张三", 25);
    }
    
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 66);
    }

    @Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("Linus Torvalds", 52);
    }

    /**
     * 给容器中注册组件:
     * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
     * 2)、@Bean[导入第三方包里面的组件]
     * 3)、@Import[快速给容器中导入一个组件]
     *      1)、@Import(要导入到容器中的组件),容器中就会自动注册这个组件,id默认是全类名
     *      2)、@ImportSelector:返回需要到导入的组件的全类名数组
     *      3)、@ImportBeanDefinitionRegistrar:手动注册bean到容器中
     */

}
使用ImportBeanDefinitionRegistrar

bean包下新建RainBow类,在condition包下新建MyImportBeanDefinitionRegistrar类,手动注册bean到容器中

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     *
     * @param annotationMetadata 当前类的注解信息
     * @param beanDefinitionRegistry BeanDefinition注册类
     *        把所有需要添加到容器中的bean,调用beanDefinitionRegistry.registerBeanDefinition()手工注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        boolean definition1 = beanDefinitionRegistry.containsBeanDefinition("com.trisirt.spring.annotation.bean.Red");
        boolean definition2 = beanDefinitionRegistry.containsBeanDefinition("com.trisirt.spring.annotation.bean.Blue");
        if(definition1 && definition2) {
            // 指定Bean的定义信息:(Bean的类型,生命周期...)
            BeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
            // 注册一个bean,指定bean名
            beanDefinitionRegistry.registerBeanDefinition("rainBow", beanDefinition);
        }
    }
}

修改MainConfig2定义,使用上面自定义的``MyImportBeanDefinitionRegistrar.class作为@Import`的参数

@Configuration
// 导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {
    @Bean("person")
    public Person person() {
        return new Person("张三", 25);
    }
    
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 66);
    }

    @Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("Linus Torvalds", 52);
    }

    /**
     * 给容器中注册组件:
     * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
     * 2)、@Bean[导入第三方包里面的组件]
     * 3)、@Import[快速给容器中导入一个组件]
     *      1)、@Import(要导入到容器中的组件),容器中就会自动注册这个组件,id默认是全类名
     *      2)、@ImportSelector:返回需要到导入的组件的全类名数组
     *      3)、@ImportBeanDefinitionRegistrar:手动注册bean到容器中
     */

}

新建测试方法testImport()

@Test
public void testImport() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    printBeans(applicationContext);
}

private void printBeans(AnnotationConfigApplicationContext applicationContext) {
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for(String name : definitionNames) {
        System.out.println(name);
    }
}

测试发现自定义的rainBow组件已经加入容器中,原因是前面判断com.trisirt.spring.annotation.bean.Redcom.trisirt.spring.annotation.bean.Blue是否存在于容器中的条件均为真,因此手动创建了一个名为rainBow的组件并加入容器中,测试程序打印结果如下:

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.trisirt.spring.annotation.bean.Color
com.trisirt.spring.annotation.bean.Red
com.trisirt.spring.annotation.bean.Blue
com.trisirt.spring.annotation.bean.Yellow
person
bill
rainBow
组件注册–使用FactoryBean

bean包下新建ColorFactoryBean

// 创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
    // 返回一个Color对象,这个对象会添加到容器中
    public Color getObject() throws Exception {
        System.out.println("ColorFactoryBean...getObject...");
        return new Color();
    }

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

    // 是单例?
    // true:这个bean是単实例,在容器中保存一份
    // false:多实例,每次获取都会创建一个新的bean
    @Override
    public boolean isSingleton() {
        return true;
    }
}

修改MainConfig2定义,增加colorFactoryBean组件注册的定义:

@Configuration
// 导入组件,id默认是组件的全类名
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

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

    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 66);
    }

    @Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("Linus Torvalds", 52);
    }

    /**
     * 给容器中注册组件:
     * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
     * 2)、@Bean[导入第三方包里面的组件]
     * 3)、@Import[快速给容器中导入一个组件]
     *      1)、@Import(要导入到容器中的组件),容器中就会自动注册这个组件,id默认是全类名
     *      2)、@ImportSelector:返回需要到导入的组件的全类名数组
     *      3)、@ImportBeanDefinitionRegistrar:手动注册bean到容器中
     * 4)、使用Spring提供的FactoryBean(工厂Bean)
     *      1)、默认获取到的是工厂bean,调用getObject创建的对象
     *      2)、要获取工厂Bean本身,我们需要给id前面加一个&,即&colorFactoryBean
     */
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}

修改测试程序testImport()

@Test
    public void testImport() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        printBeans(applicationContext);

        // 工厂Bean获取的是调用getObject创建的对象
        Object bean = applicationContext.getBean("colorFactoryBean");
        Object bean2 = applicationContext.getBean("colorFactoryBean");
        System.out.println("bean的类型:" + bean.getClass());
        System.out.println(bean == bean2);

    }

测试结果如下:

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.trisirt.spring.annotation.bean.Color
com.trisirt.spring.annotation.bean.Red
com.trisirt.spring.annotation.bean.Blue
com.trisirt.spring.annotation.bean.Yellow
person
bill
colorFactoryBean
rainBow
ColorFactoryBean...getObject...
bean的类型:class com.trisirt.spring.annotation.bean.Color
true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值