spring注解驱动第三节之Bean的生命周期

3. Bean的生命周期

bean的生命周期指的是bean创建—初始化—-销毁的过程
我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
构造(对象创建)
单实例:在容器启动的时候创建对象
多实例:容器不会管理这个bean;容器不会调用销毁方法;

3.1 @Bean指定初始化方法和销毁方法
  • 修改之前创建的User.java,增加初始化和销毁方法,方法体与方法名称自定义即可
package com.ddf.spring.annotation.entity;

/**
 * @author DDf on 2018/7/19
 */
public class User {

    private Integer id;
    private String userName;
    private String password;
    private String tel;

    public void init() {
        System.out.println("User创建后调用初始化方法..........");
    }

    public void destory() {
        System.out.println("User销毁后调用销毁方法....通过@Bean的destoryMethod指定销毁方法......");
    }

    public User() {
        System.out.println("User创建完成...通过@Bean的initMethod调用初始化方法............");
    }

    public User(Integer id, String userName, String password, String tel) {
        this.id = id;
        this.userName = userName;
        this.password = password;
        this.tel = tel;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }
}
  • 修改主配置类AnnotationConfiguration.java,使用@Bean注册User的时候指定初始化和销毁方法
    initMethod 指定Bean创建后调用的初始化方法
    destroyMethod 指定Bean在销毁后会调用的方法
package com.ddf.spring.annotation.configuration;

import com.ddf.spring.annotation.service.*;
import com.ddf.spring.annotation.entity.User;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;

/**
 * @author DDf on 2018/7/19
 * @Configuration 表明当前类是一个配置类
 * @ComponentScan 指定扫描的包路径,并且配置了excludeFilters来排除注解类型为@Controller的不纳入容器中,
 * 排除符合自定义ExcludeTypeFilter类中规则的类
 * @Import 导入组件,可以直接导入普通类,或者通过ImportSelector接口或者ImportBeanDefinitionRegistrar接口来自定义导入
 */
@Configuration
@ComponentScan(value = "com.ddf.spring.annotation", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class),
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = ExcludeTypeFilter.class)
})
@Import(value = {ImportBean.class, CustomImportSelector.class, CustomImportBeanDefinitionRegistrar.class})
public class AnnotationConfiguration {

    /**
     * 注入一个Type为User(方法返回值)的bean,bean的名称为user(方法名)
     * initMethod 指定Bean创建后调用的初始化方法
     * destroyMethod 指定Bean在销毁后会调用的方法
     * @return
     */
    @Bean(initMethod = "init", destroyMethod = "destory")
    public User user() {
        return new User();
    }


    /**
     * 测试@Conditional 满足{@link DevelopmentProfileCondition} 这个类的条件返回true则当前Bean能够成功注入,反之不能
     *
     * @return
     */
    @Bean
    @Conditional({DevelopmentProfileCondition.class})
    public DevelopmentBean DevelopmentBean() {
        return new DevelopmentBean();
    }


    /**
     * 满足{@link ProductionProfileCondition} 这个类的条件返回true则当前Bean能够成功注入,反之不能
     *
     * @return
     */
    @Bean
    @Conditional({ProductionProfileCondition.class})
    public ProductionBean ProductionBean() {
        return new ProductionBean();
    }


    /**
     * 使用FactoryBean工厂来注册组件
     * @return
     */
    @Bean
    public FactoryPrototypeBeanConfiguration factoryPrototypeBeanConfiguration() {
        return new FactoryPrototypeBeanConfiguration();
    }

    /**
     * 使用FactoryBean工厂来注册组件
     * @return
     */
    @Bean
    public FactorySingletonBeanConfiguration factorySingletonBeanConfiguration() {
        return new FactorySingletonBeanConfiguration();
    }
}
3.2 InitializingBeanDisposableBean接口

将要创建指定初始化和销毁方法的类实现初始化接口InitializingBean,如果需要指定销毁方法实现DisposableBean接口

  • 创建一个实现了InitializingBeanDisposableBean接口的Bean
package com.ddf.spring.annotation.service;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author DDf on 2018/8/1
 * 实现InitializingBean接口的afterPropertiesSet方法在Bean被创建后会自动调用该初始化方法
 * 实现DisposableBean接口的destroy方法会在容器会Bean被销毁时时调用该方法
 */
public class InitAndDisposableBean implements InitializingBean, DisposableBean {
    public InitAndDisposableBean() {
        System.out.println("InitAndDisposableBean创建完成。。。。。。。。。。。。");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("InitAndDisposableBean容器销毁,实现DisposableBean接口调用销毁方法...........");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitAndDisposableBean创建后实现InitializingBean调用初始化方法。。。。。。。。。。。。");
    }
}
3.3 @PostConstruct@PreDestroy注解

在需要指定初始化和销毁方法的Bean里创建对应的初始化和销毁方法,使用对应注解标注即可。
使用@PostConstruct指定Bean的初始化方法
使用@PreDestroy指定Bean销毁后调用的方法

  • 创建PostConstructAndPreDestoryBean.java
package com.ddf.spring.annotation.service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author DDf on 2018/8/1
 * 使用JSR250注解实现Bean的初始化方法和销毁方法调用
 */
public class PostConstructAndPreDestoryBean {
    public PostConstructAndPreDestoryBean() {
        System.out.println("PostConstructAndPreDestoryBean创建完成.......");
    }

    /**
     * 使用@PostConstruct指定Bean的初始化方法
     */
    @PostConstruct
    public void init() {
        System.out.println("PostConstructAndPreDestoryBean创建完成,使用@PostConstruct注解来调用初始化方法。。。。");
    }


    /**
     * 使用@PreDestroy指定Bean销毁后调用的方法
     */
    @PreDestroy
    public void destroy() {
        System.out.println("PostConstructAndPreDestoryBean容器销毁,使用@PreDestroy注解来指定调用销毁方法。。。。");
    }
}
3.4 修改主启动类Application.java

以上三种形式,现在统一修改主启动类,然后集中验证,修改主启动类,在主程序最后关闭IOC容器

package com.ddf.spring.annotation;

import com.ddf.spring.annotation.service.*;
import com.ddf.spring.annotation.configuration.AnnotationConfiguration;
import com.ddf.spring.annotation.configuration.FactoryPrototypeBeanConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author DDf on 2018/7/19
 */
public class Application {
    public static void main(String[] args) {
        System.out.println("-----------------------IOC容器初始化-------------------------");
        // 创建一个基于配置类启动的IOC容器,如果主配置类扫描包的路径下包含其他配置类,则其他配置类可以被自动识别
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationConfiguration.class);
        System.out.println("-----------------------IOC容器初始化完成-------------------------\n");
        // 获取当前IOC中所有bean的名称,即使是懒加载类型的bean也会获取到
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        // 打印当前IOC中对应名称的bean和bean的类型
        for (String name : definitionNames) {
            // 这个会影响到测试懒加载的效果,如果需要测试懒加载,这行代码需要注释掉,因为getBean方法一旦调用则会初始化
            Object bean = applicationContext.getBean(name);
            System.out.println("bean name:" + name + ", type: " + bean.getClass());
        }

        // 测试@Scope bean的作用域
        testPrototypeScopeService(applicationContext);
        // 测试单实例bean的@Lazy懒加载
        testLazyBeanService(applicationContext);
        // 测试FactoryBean接口导入单实例与Prototype作用域的组件
        testFactoryBeanPrototypeBean(applicationContext);

        // 销毁容器
        applicationContext.close();
    }


    /**
     * 测试@Scope bean的作用域
     *
     * @param applicationContext
     */
    public static void testPrototypeScopeService(ApplicationContext applicationContext) {
        System.out.println("\n-----------------------测试@Scope开始-------------------------");
        UserService userService = (UserService) applicationContext.getBean("userService");
        UserService userService1 = applicationContext.getBean(UserService.class);
        System.out.println("默认单实例bean UserService是否相等 " + (userService == userService1));

        PrototypeScopeService prototypeScopeService = applicationContext.getBean(PrototypeScopeService.class);
        PrototypeScopeService prototypeScopeService1 = applicationContext.getBean(PrototypeScopeService.class);
        System.out.println("PrototypeScopeService prototype scope作用域是否相等: " + (prototypeScopeService == prototypeScopeService1));
        System.out.println("-----------------------测试@Scope结束-------------------------\n");
    }

    /**
     * 测试单实例bean的懒加载,只有等使用的时候再创建实例。
     * IOC容器启动后不会创建该bean的实例,如果是在该方法中才创建这个bean的实例,并且获得的两个bean是同一个的话,则测试通过。
     */
    public static void testLazyBeanService(ApplicationContext applicationContext) {
        System.out.println("\n---------------测试单实例bean的@Lazy懒加载开始----------------------");
        LazyBeanService lazyBeanService = applicationContext.getBean(LazyBeanService.class);
        LazyBeanService lazyBeanService1 = applicationContext.getBean(LazyBeanService.class);
        System.out.println("lazyBeanService==lazyBeanService1?: " + (lazyBeanService == lazyBeanService1));
        System.out.println("---------------测试单实例bean的@Lazy懒加载结束----------------------\n");
    }


    /**
     * 测试通过FactoryBean接口导入单实例与Prototype作用域的组件,根据打印可以看出FactoryBean创建的单实例Bean都是懒加载的
     * @param applicationContext
     */
    public static void testFactoryBeanPrototypeBean(ApplicationContext applicationContext) {
        System.out.println("\n----------测试通过FactoryBean注册单实例和Prototype作用域的组件开始----------");
        FactorySingletonBean factorySingletonBean = applicationContext.getBean(FactorySingletonBean.class);
        FactorySingletonBean factorySingletonBean1 = applicationContext.getBean(FactorySingletonBean.class);

        FactoryPrototypeBean factoryPrototypeBean = applicationContext.getBean(FactoryPrototypeBean.class);
        FactoryPrototypeBean factoryPrototypeBean1 = applicationContext.getBean(FactoryPrototypeBean.class);

        System.out.println("单实例factorySingletonBean==factorySingletonBean1?" + (factorySingletonBean==factorySingletonBean1));

        System.out.println("Prototype作用域factoryPrototypeBean==factoryPrototypeBean1?" + (factoryPrototypeBean==factoryPrototypeBean1));
        System.out.println("----------测试通过FactoryBean注册单实例和Prototype作用域的组件结束----------\n");
    }
}
3.5 验证结果

运行主启动类,打印如下,可以看到容器在IOC容器创建后同时调用了初始化方法,并且在IOC容器关闭的时候调用了对应Bean的销毁方法

-----------------------IOC容器初始化-------------------------
八月 01, 2018 11:08:03 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5197848c: startup date [Wed Aug 01 23:08:03 CST 2018]; root of context hierarchy
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.Application
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.CustomImportBeanDefinitionRegistrar
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.CustomImportSelector
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.DevelopmentProfileCondition
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.ExcludeTypeFilter
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.FactoryPrototypeBeanConfiguration
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.FactorySingletonBeanConfiguration
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.ProductionProfileCondition
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.controller.UserController
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.entity.User
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.DevelopmentBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.DevelopmentBeanLog
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.ExcludeFilterService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.FactoryBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.FactoryPrototypeBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.FactorySingletonBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ImportBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ImportBeanDefinitionRegistrarBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ImportSelectorBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.IncludeFilterService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.InitAndDisposableBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.LazyBeanService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.PostConstructAndPreDestoryBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ProductionBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ProductionBeanLog
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.PrototypeScopeService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.UserService
DevelopmentProfileCondition profile: dev
ProductionProfileCondition profile: dev
八月 01, 2018 11:08:04 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
UserService创建完成...................
ImportBean创建完成(测试@Import导入组件)..........
ImportSelectorBean创建完成,测试@Import通过ImportSelector接口导入组件
User创建完成...通过@Bean的initMethod调用初始化方法............
User创建后调用初始化方法..........
DevelopmentBeanLog创建完成.......测试@Condition........
DevelopmentBean创建完成.....测试@Condition........
InitAndDisposableBean创建完成。。。。。。。。。。。。
InitAndDisposableBean创建后实现InitializingBean调用初始化方法。。。。。。。。。。。。
PostConstructAndPreDestoryBean创建完成.......
PostConstructAndPreDestoryBean创建完成,使用@PostConstruct注解来调用初始化方法。。。。
ImportBeanDefinitionRegistrarBean创建完成,测试@Import接口通过ImportBeanDefinitionRegistrar接口注入组件。。。。。
-----------------------IOC容器初始化完成-------------------------

bean name:org.springframework.context.annotation.internalConfigurationAnnotationProcessor, type: class org.springframework.context.annotation.ConfigurationClassPostProcessor
bean name:org.springframework.context.annotation.internalAutowiredAnnotationProcessor, type: class org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
bean name:org.springframework.context.annotation.internalRequiredAnnotationProcessor, type: class org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
bean name:org.springframework.context.annotation.internalCommonAnnotationProcessor, type: class org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
bean name:org.springframework.context.event.internalEventListenerProcessor, type: class org.springframework.context.event.EventListenerMethodProcessor
bean name:org.springframework.context.event.internalEventListenerFactory, type: class org.springframework.context.event.DefaultEventListenerFactory
bean name:annotationConfiguration, type: class com.ddf.spring.annotation.configuration.AnnotationConfiguration$$EnhancerBySpringCGLIB$$7081dc62
LazyBeanService创建完成...............
bean name:lazyBeanService, type: class com.ddf.spring.annotation.service.LazyBeanService
PrototypeScopeService创建完成。。。。。。。。
bean name:prototypeScopeService, type: class com.ddf.spring.annotation.service.PrototypeScopeService
bean name:userService, type: class com.ddf.spring.annotation.service.UserService
bean name:com.ddf.spring.annotation.bean.ImportBean, type: class com.ddf.spring.annotation.bean.ImportBean
bean name:com.ddf.spring.annotation.bean.ImportSelectorBean, type: class com.ddf.spring.annotation.bean.ImportSelectorBean
bean name:user, type: class com.ddf.spring.annotation.entity.User
bean name:DevelopmentBeanLog, type: class com.ddf.spring.annotation.bean.DevelopmentBeanLog
bean name:DevelopmentBean, type: class com.ddf.spring.annotation.bean.DevelopmentBean
FactoryPrototypeBean创建完成....,测试通过FactoryBean来注册Prototype组件。。。。
bean name:factoryPrototypeBeanConfiguration, type: class com.ddf.spring.annotation.bean.FactoryPrototypeBean
FactorySingletonBean创建完成。。。。,测试通过FactoryBean来注册单实例组件。。。。
bean name:factorySingletonBeanConfiguration, type: class com.ddf.spring.annotation.bean.FactorySingletonBean
bean name:initAndDisposableBean, type: class com.ddf.spring.annotation.bean.InitAndDisposableBean
bean name:postConstructAndPreDestoryBean, type: class com.ddf.spring.annotation.bean.PostConstructAndPreDestoryBean
bean name:importBeanDefinitionRegistrarBean, type: class com.ddf.spring.annotation.bean.ImportBeanDefinitionRegistrarBean

-----------------------测试@Scope开始-------------------------
默认单实例bean UserService是否相等 true
PrototypeScopeService创建完成。。。。。。。。
PrototypeScopeService创建完成。。。。。。。。
PrototypeScopeService prototype scope作用域是否相等: false
-----------------------测试@Scope结束-------------------------


---------------测试单实例bean的@Lazy懒加载开始----------------------
lazyBeanService==lazyBeanService1?: true
---------------测试单实例bean的@Lazy懒加载结束----------------------


----------测试通过FactoryBean注册单实例和Prototype作用域的组件开始----------
FactoryPrototypeBean创建完成....,测试通过FactoryBean来注册Prototype组件。。。。
FactoryPrototypeBean创建完成....,测试通过FactoryBean来注册Prototype组件。。。。
单实例factorySingletonBean==factorySingletonBean1?true
Prototype作用域factoryPrototypeBean==factoryPrototypeBean1?false
----------测试通过FactoryBean注册单实例和Prototype作用域的组件结束----------

八月 01, 2018 11:08:04 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5197848c: startup date [Wed Aug 01 23:08:03 CST 2018]; root of context hierarchy
PostConstructAndPreDestoryBean容器销毁,使用@PreDestroy注解来指定调用销毁方法。。。。
InitAndDisposableBean容器销毁,实现DisposableBean接口调用销毁方法...........
User销毁后调用销毁方法....通过@Bean的destoryMethod指定销毁方法......

Process finished with exit code 0
3.6 BeanPostProcessor接口

参见org.springframework.beans.factory.config.BeanPostProcessor,该接口可以在每个bean的初始化方法调用之前和初始化方法调用之后执行指定的方法,
postProcessBeforeInitialization()在每个bean创建之后的初始化方法之前调用, postProcessAfterInitialization在每个bean的初始化方法执行之后被调用,执行实际千万和前面提到的初始化方法和销毁方法区分开。该方法通常用户修改预定义的bean的属性值,可以实现该接口进行覆盖。更详细参见章节扩展原理之1. BeanFactoryPostProcessor接口

  • 新建CustomBeanPostProcessor.java实现BeanPostProcessor接口
package com.ddf.spring.annotation.configuration;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author DDf on 2018/8/2
 * BeanPostProcessor接口为bean的后置处理器,用来在bean的初始化前后做一些工作,需要将该类加入到容器中。
 * 需要理解的是,这个会在每个bean的生命周期内都会生效
 * postProcessBeforeInitialization()方法是在bean的初始化方法之前调用
 * postProcessAfterInitialization()方法是在bean的初始化方法之前调用之后执行
 *
 * 原理:
 * 遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,
 * * 一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization
 * *
 * * BeanPostProcessor原理
 * * populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
 * * initializeBean
 * * {
 * * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 * * invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
 * * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 * *}
 *
 * Spring底层对 BeanPostProcessor 的使用;
 * * bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor;
 */
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

    /**
     * 在每个bean创建之后的初始化方法之前调用
     * @param bean 当前实例化的bean
     * @param beanName bean的名称
     * @return 返回实例化的bean或者可以对对象进行再封装返回
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【" + bean + "】");
        return bean;
    }


    /**
     * 在每个bean的初始化方法执行之后被调用
     * @param bean 当前实例化的bean
     * @param beanName bean的名称
     * @return 返回实例化的bean或者可以对对象进行再封装返回
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【" + bean + "】");
        return bean;
    }
}
  • 运行主启动类Application.java
package com.ddf.spring.annotation;

import com.ddf.spring.annotation.service.*;
import com.ddf.spring.annotation.configuration.AnnotationConfiguration;
import com.ddf.spring.annotation.configuration.FactoryPrototypeBeanConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author DDf on 2018/7/19
 */
public class Application {
    public static void main(String[] args) {
        System.out.println("-----------------------IOC容器初始化-------------------------");
        // 创建一个基于配置类启动的IOC容器,如果主配置类扫描包的路径下包含其他配置类,则其他配置类可以被自动识别
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationConfiguration.class);
        System.out.println("-----------------------IOC容器初始化完成-------------------------\n");
        // 获取当前IOC中所有bean的名称,即使是懒加载类型的bean也会获取到
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        // 打印当前IOC中对应名称的bean和bean的类型
        for (String name : definitionNames) {
            // 这个会影响到测试懒加载的效果,如果需要测试懒加载,这行代码需要注释掉,因为getBean方法一旦调用则会初始化
            Object bean = applicationContext.getBean(name);
            System.out.println("bean name:" + name + ", type: " + bean.getClass());
        }

        // 测试@Scope bean的作用域
        testPrototypeScopeService(applicationContext);
        // 测试单实例bean的@Lazy懒加载
        testLazyBeanService(applicationContext);
        // 测试FactoryBean接口导入单实例与Prototype作用域的组件
        testFactoryBeanPrototypeBean(applicationContext);

        // 销毁容器
        applicationContext.close();
    }


    /**
     * 测试@Scope bean的作用域
     *
     * @param applicationContext
     */
    public static void testPrototypeScopeService(ApplicationContext applicationContext) {
        System.out.println("\n-----------------------测试@Scope开始-------------------------");
        UserService userService = (UserService) applicationContext.getBean("userService");
        UserService userService1 = applicationContext.getBean(UserService.class);
        System.out.println("默认单实例bean UserService是否相等 " + (userService == userService1));

        PrototypeScopeService prototypeScopeService = applicationContext.getBean(PrototypeScopeService.class);
        PrototypeScopeService prototypeScopeService1 = applicationContext.getBean(PrototypeScopeService.class);
        System.out.println("PrototypeScopeService prototype scope作用域是否相等: " + (prototypeScopeService == prototypeScopeService1));
        System.out.println("-----------------------测试@Scope结束-------------------------\n");
    }

    /**
     * 测试单实例bean的懒加载,只有等使用的时候再创建实例。
     * IOC容器启动后不会创建该bean的实例,如果是在该方法中才创建这个bean的实例,并且获得的两个bean是同一个的话,则测试通过。
     */
    public static void testLazyBeanService(ApplicationContext applicationContext) {
        System.out.println("\n---------------测试单实例bean的@Lazy懒加载开始----------------------");
        LazyBeanService lazyBeanService = applicationContext.getBean(LazyBeanService.class);
        LazyBeanService lazyBeanService1 = applicationContext.getBean(LazyBeanService.class);
        System.out.println("lazyBeanService==lazyBeanService1?: " + (lazyBeanService == lazyBeanService1));
        System.out.println("---------------测试单实例bean的@Lazy懒加载结束----------------------\n");
    }


    /**
     * 测试通过FactoryBean接口导入单实例与Prototype作用域的组件,根据打印可以看出FactoryBean创建的单实例Bean都是懒加载的
     * @param applicationContext
     */
    public static void testFactoryBeanPrototypeBean(ApplicationContext applicationContext) {
        System.out.println("\n----------测试通过FactoryBean注册单实例和Prototype作用域的组件开始----------");
        FactorySingletonBean factorySingletonBean = applicationContext.getBean(FactorySingletonBean.class);
        FactorySingletonBean factorySingletonBean1 = applicationContext.getBean(FactorySingletonBean.class);

        FactoryPrototypeBean factoryPrototypeBean = applicationContext.getBean(FactoryPrototypeBean.class);
        FactoryPrototypeBean factoryPrototypeBean1 = applicationContext.getBean(FactoryPrototypeBean.class);

        System.out.println("单实例factorySingletonBean==factorySingletonBean1?" + (factorySingletonBean==factorySingletonBean1));

        System.out.println("Prototype作用域factoryPrototypeBean==factoryPrototypeBean1?" + (factoryPrototypeBean==factoryPrototypeBean1));
        System.out.println("----------测试通过FactoryBean注册单实例和Prototype作用域的组件结束----------\n");
    }
}
  • 控制台打印如下,仔细观察BeanPostProcessor接口方法的执行时机,是在每个bean的初始化方法之前和之后两个地方呗调用
-----------------------IOC容器初始化-------------------------
八月 02, 2018 10:21:08 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5197848c: startup date [Thu Aug 02 22:21:08 CST 2018]; root of context hierarchy
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.Application
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.ApplicationContextUtil
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.CustomBeanPostProcessor
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.CustomImportBeanDefinitionRegistrar
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.CustomImportSelector
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.DevelopmentProfileCondition
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.ExcludeTypeFilter
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.FactoryPrototypeBeanConfiguration
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.FactorySingletonBeanConfiguration
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.configuration.ProductionProfileCondition
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.controller.UserController
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.entity.User
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.DevelopmentBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.DevelopmentBeanLog
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.ExcludeFilterService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.FactoryBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.FactoryPrototypeBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.FactorySingletonBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ImportBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ImportBeanDefinitionRegistrarBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ImportSelectorBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.IncludeFilterService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.InitAndDisposableBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.LazyBeanService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.PostConstructAndPreDestoryBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ProductionBean
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.bean.ProductionBeanLog
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.PrototypeScopeService
自定义扫描类规则当前扫描类为: com.ddf.spring.annotation.service.UserService
DevelopmentProfileCondition profile: prd
ProductionProfileCondition profile: prd
八月 02, 2018 10:21:08 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【org.springframework.context.event.EventListenerMethodProcessor@77be656f】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【org.springframework.context.event.EventListenerMethodProcessor@77be656f】
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【org.springframework.context.event.DefaultEventListenerFactory@221af3c0】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【org.springframework.context.event.DefaultEventListenerFactory@221af3c0】
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.configuration.AnnotationConfiguration$$EnhancerBySpringCGLIB$$a202c61@23a5fd2】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.configuration.AnnotationConfiguration$$EnhancerBySpringCGLIB$$a202c61@23a5fd2】
UserService创建完成...................
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.service.UserService@78a2da20】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.service.UserService@78a2da20】
ImportBean创建完成(测试@Import导入组件)..........
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ImportBean@dd3b207】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ImportBean@dd3b207】
ImportSelectorBean创建完成,测试@Import通过ImportSelector接口导入组件
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ImportSelectorBean@551bdc27】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ImportSelectorBean@551bdc27】
User创建完成...通过@Bean的initMethod调用初始化方法............
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.entity.User@564718df】
User创建后调用初始化方法..........
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.entity.User@564718df】
ProductionBeanLog创建完成.......测试@Condition............
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ProductionBeanLog@18a70f16】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ProductionBeanLog@18a70f16】
ProductionBean创建完成......测试@Condition.......
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ProductionBean@62e136d3】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ProductionBean@62e136d3】
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.configuration.FactoryPrototypeBeanConfiguration@4206a205】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.configuration.FactoryPrototypeBeanConfiguration@4206a205】
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.configuration.FactorySingletonBeanConfiguration@c540f5a】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.configuration.FactorySingletonBeanConfiguration@c540f5a】
InitAndDisposableBean创建完成。。。。。。。。。。。。
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.InitAndDisposableBean@4d826d77】
InitAndDisposableBean创建后实现InitializingBean调用初始化方法。。。。。。。。。。。。
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.InitAndDisposableBean@4d826d77】
PostConstructAndPreDestoryBean创建完成.......
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.PostConstructAndPreDestoryBean@44a664f2】
PostConstructAndPreDestoryBean创建完成,使用@PostConstruct注解来调用初始化方法。。。。
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.PostConstructAndPreDestoryBean@44a664f2】
ImportBeanDefinitionRegistrarBean创建完成,测试@Import接口通过ImportBeanDefinitionRegistrar接口注入组件。。。。。
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ImportBeanDefinitionRegistrarBean@7f9fcf7f】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.ImportBeanDefinitionRegistrarBean@7f9fcf7f】
-----------------------IOC容器初始化完成-------------------------

bean name:org.springframework.context.annotation.internalConfigurationAnnotationProcessor, type: class org.springframework.context.annotation.ConfigurationClassPostProcessor
bean name:org.springframework.context.annotation.internalAutowiredAnnotationProcessor, type: class org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
bean name:org.springframework.context.annotation.internalRequiredAnnotationProcessor, type: class org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
bean name:org.springframework.context.annotation.internalCommonAnnotationProcessor, type: class org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
bean name:org.springframework.context.event.internalEventListenerProcessor, type: class org.springframework.context.event.EventListenerMethodProcessor
bean name:org.springframework.context.event.internalEventListenerFactory, type: class org.springframework.context.event.DefaultEventListenerFactory
bean name:annotationConfiguration, type: class com.ddf.spring.annotation.configuration.AnnotationConfiguration$$EnhancerBySpringCGLIB$$a202c61
bean name:customBeanPostProcessor, type: class com.ddf.spring.annotation.configuration.CustomBeanPostProcessor
LazyBeanService创建完成...............
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.service.LazyBeanService@2c34f934】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.service.LazyBeanService@2c34f934】
bean name:lazyBeanService, type: class com.ddf.spring.annotation.service.LazyBeanService
PrototypeScopeService创建完成。。。。。。。。
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.service.PrototypeScopeService@12d3a4e9】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.service.PrototypeScopeService@12d3a4e9】
bean name:prototypeScopeService, type: class com.ddf.spring.annotation.service.PrototypeScopeService
bean name:userService, type: class com.ddf.spring.annotation.service.UserService
bean name:com.ddf.spring.annotation.bean.ImportBean, type: class com.ddf.spring.annotation.bean.ImportBean
bean name:com.ddf.spring.annotation.bean.ImportSelectorBean, type: class com.ddf.spring.annotation.bean.ImportSelectorBean
bean name:user, type: class com.ddf.spring.annotation.entity.User
bean name:prdServiceLog, type: class com.ddf.spring.annotation.bean.ProductionBeanLog
bean name:ProductionBean, type: class com.ddf.spring.annotation.bean.ProductionBean
FactoryPrototypeBean创建完成....,测试通过FactoryBean来注册Prototype组件。。。。
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.FactoryPrototypeBean@240237d2】
bean name:factoryPrototypeBeanConfiguration, type: class com.ddf.spring.annotation.bean.FactoryPrototypeBean
FactorySingletonBean创建完成。。。。,测试通过FactoryBean来注册单实例组件。。。。
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.FactorySingletonBean@25a65b77】
bean name:factorySingletonBeanConfiguration, type: class com.ddf.spring.annotation.bean.FactorySingletonBean
bean name:initAndDisposableBean, type: class com.ddf.spring.annotation.bean.InitAndDisposableBean
bean name:postConstructAndPreDestoryBean, type: class com.ddf.spring.annotation.bean.PostConstructAndPreDestoryBean
bean name:importBeanDefinitionRegistrarBean, type: class com.ddf.spring.annotation.bean.ImportBeanDefinitionRegistrarBean

-----------------------测试@Scope开始-------------------------
默认单实例bean UserService是否相等 true
PrototypeScopeService创建完成。。。。。。。。
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.service.PrototypeScopeService@548a102f】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.service.PrototypeScopeService@548a102f】
PrototypeScopeService创建完成。。。。。。。。
BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【com.ddf.spring.annotation.service.PrototypeScopeService@5762806e】
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.service.PrototypeScopeService@5762806e】
PrototypeScopeService prototype scope作用域是否相等: false
-----------------------测试@Scope结束-------------------------


---------------测试单实例bean的@Lazy懒加载开始----------------------
lazyBeanService==lazyBeanService1?: true
---------------测试单实例bean的@Lazy懒加载结束----------------------


----------测试通过FactoryBean注册单实例和Prototype作用域的组件开始----------
FactoryPrototypeBean创建完成....,测试通过FactoryBean来注册Prototype组件。。。。
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.FactoryPrototypeBean@17c386de】
FactoryPrototypeBean创建完成....,测试通过FactoryBean来注册Prototype组件。。。。
BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【com.ddf.spring.annotation.bean.FactoryPrototypeBean@5af97850】
单实例factorySingletonBean==factorySingletonBean1?true
Prototype作用域factoryPrototypeBean==factoryPrototypeBean1?false
----------测试通过FactoryBean注册单实例和Prototype作用域的组件结束----------

PostConstructAndPreDestoryBean容器销毁,使用@PreDestroy注解来指定调用销毁方法。。。。
InitAndDisposableBean容器销毁,实现DisposableBean接口调用销毁方法...........
User销毁后调用销毁方法....通过@Bean的destoryMethod指定销毁方法......
八月 02, 2018 10:21:08 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5197848c: startup date [Thu Aug 02 22:21:08 CST 2018]; root of context hierarchy

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值