Spring源码(2)BeanFactory工厂后置处理器、Bean的后置处理器、ApplicationContext容器、Bean的生命周期

1、目标

本文的主要目标是学习BeanFactory工厂后置处理器、Bean的后置处理器、ApplicationContext容器、Bean的生命周期

2、BeanFactory

2.1 BeanFactory工厂后置处理器

@SpringBootApplication
@Log4j2
public class SpringBootDemoApplication {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        // BeanFactory对象注册BeanDefinition对象
        beanFactory.registerBeanDefinition("config", beanDefinition);

        // BeanFactory对象添加后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        // 执行BeanFactoryPostProcessor后置处理器的postProcessBeanFactory方法才会将@Bean注解的对象注入到容器中
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()) {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        }

        // 输出注册的bean的名字
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

    }

    @Configuration
    static class Config {
        @Bean
        public Bean01 bean01() {
            return new Bean01();
        }
        @Bean
        public Bean02 bean02() {
            return new Bean02();
        }
    }

    static class Bean01 {
        @Autowired
        private Bean02 bean02;
    }

    static class Bean02 {

    }
}

DefaultListableBeanFactory是默认的BeanFactory对象,BeanFactory对象可以注册BeanDefinition对象

BeanFactoryPostProcessor这是bean工厂的后置处理器,通过postProcessBeanFactory方法可以添加一些bean对象的定义

输出结果是:

在这里插入图片描述

可以看到,BeanFactory容器中包含了config、bean01、bean02和后置处理器等对象

internalAutowiredAnnotationProcessor后置处理器是bean工厂的后置处理器,专门用来处理器@Autowired注解的

internalCommonAnnotationProcessor后置处理器是bean工厂的后置处理器,专门用来处理@Resource注解的

2.2 Bean的后置处理器

2.2.1 添加Bean的后置处理器可以依赖注入成功
Bean01 bean01 = beanFactory.getBean(Bean01.class);
System.out.println("bean01 = " + bean01);
Bean02 bean02 = beanFactory.getBean(Bean02.class);
System.out.println("bean02 = " + bean02);
bean02 = beanFactory.getBean(Bean01.class).getBean02();  //为null说明依赖注入失败了
System.out.println("bean02 = " + bean02);

获取Bean01对象中依赖注入的Bean02对象,会返回null,因为没有将bean的后置处理器放到添加到BeanFactory中

在这里插入图片描述

没有依赖注入bean02对象

// 执行BeanPostProcessor后置处理器的方法会对bean的生命周期提供扩展,比如对@Autowired和@Resource注解等
Collection<BeanPostProcessor> values = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
values.forEach(beanFactory::addBeanPostProcessor);

执行BeanPostProcessor后置处理器的addBeanPostProcessor方法会对bean的生命周期提供扩展

在这里插入图片描述

添加了在bean01对象中的bean02对象会依赖注入成功

2.2.2 @Autowired和@Resource注解解析的优先级顺序

希望看到@Autowired和@Resource注解依赖注入的顺序,可以打印bean的后置处理器BeanPostProcessor

// 执行BeanPostProcessor后置处理器的方法会对bean的生命周期提供扩展,比如对@Autowired和@Resource注解等
Collection<BeanPostProcessor> values = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
 values.forEach(beanPostProcessor -> {
     System.out.println("beanPostProcessor = " + beanPostProcessor);
     beanFactory.addBeanPostProcessor(beanPostProcessor);
 });

遍历并打印所有的BeanPostProcessor对象

在这里插入图片描述

可以看到Autowired注解的bean后置处理器比Resource注解的bean后置处理器优先执行,因此如果这两个注解同时存在的话会优先解析@Autowired注解

// 执行BeanPostProcessor后置处理器的方法会对bean的生命周期提供扩展,比如对@Autowired和@Resource注解等
Collection<BeanPostProcessor> values = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
 values.stream().sorted(beanFactory.getDependencyComparator()).forEach(beanPostProcessor -> {
     System.out.println("beanPostProcessor = " + beanPostProcessor);
     beanFactory.addBeanPostProcessor(beanPostProcessor);
 });

这个根据Stream流的sorted进行排序,是根据BeanFactory对象的getDependencyComparator方法进行排序

在这里插入图片描述

AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)方法是设置BeanFactory对象的依赖比较器

在这里插入图片描述

AutowiredAnnotationBeanPostProcessor这个bean的后置处理器是依赖注入@Autowired注解的bean对象,它的order设置成Integer的最大值减去2

在这里插入图片描述

CommonAnnotationBeanPostProcessor这个bean的后置处理器是依赖注入@Resource注解的bean对象,它的order设置成Integer的最大值减去3

order的值越小,优先级越高

在这里插入图片描述

可以看到,根据order进行排序,CommonAnnotationBeanPostProcessor的@Resource注解解析的bean对象优先级比AutowiredAnnotationBeanPostProcessor的@Autowried注解解析的bean对象的优先级更高

2.3 加载容器中的对象

System.out.println("==========================");

Bean01 bean01 = beanFactory.getBean(Bean01.class);
System.out.println("bean01 = " + bean01);
Bean02 bean02 = beanFactory.getBean(Bean02.class);
System.out.println("bean02 = " + bean02);
bean02 = beanFactory.getBean(Bean01.class).getBean02();  //为null说明依赖注入失败了
System.out.println("bean02 = " + bean02);

默认是懒加载的,getBean用到这个对象的时候才会执行构造器

在这里插入图片描述

调用getBean方法才会执行构造器

// 实例化单例对象
beanFactory.preInstantiateSingletons();

System.out.println("==========================");

Bean01 bean01 = beanFactory.getBean(Bean01.class);
System.out.println("bean01 = " + bean01);
Bean02 bean02 = beanFactory.getBean(Bean02.class);
System.out.println("bean02 = " + bean02);
bean02 = beanFactory.getBean(Bean01.class).getBean02();  //为null说明依赖注入失败了
System.out.println("bean02 = " + bean02);

beanFactory.preInstantiateSingletons()方法会初始化容器中的单例对象

在这里插入图片描述

默认情况下是懒加载的,beanFactory.preInstantiateSingletons()方法会初始化容器中的单例对象

2.4 总结

因此,BeanFactory对象不会主动调用BeanFactory工厂的后置处理器,不会主动调用Bean的后置处理器,不会主动初始化单例对象,不会解析#{}和${}

3、ApplicationContext

AnnotationConfigServletWebServerApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);

AnnotationConfigServletWebServerApplicationContex是一个基于注解配置的web服务器的容器applicationContext

@Configuration
static class WebConfig {
    // 配置内嵌容器
    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
        return new TomcatServletWebServerFactory();
    }
    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }
    // 注册DispatcherServlet到Tomcat服务器
    @Bean
    public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
        return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
    }
    // Controller接口
    @Bean("/hello")
    public Controller controller() {
        return (httpServletRequest, httpServletResponse) -> {
            httpServletResponse.getWriter().println("hello");
            return null;
        };
    }
}

WebConfig是一个配置类,它在容器中创建了内嵌容器TomcatServletWebServerFactory,它创建了DispatcherServlet对象,它创建了DispatcherServletRegistrationBean对象用来注册DispatcherServlet对象到Tomcat服务器,还创建了一个Controller,这个Controller是一个接口,它在springframework.web.servlet.mvc包下,@Bean上写上/hello表示请求路径是/hello

浏览器输入:localhost:8080/hello,浏览器会返回hello

问题:启动服务失败

在这里插入图片描述

启动SpringBoot时发现DispatcherServletRegistrationBean有多个Bean实例,因此容器不知道选择哪个,因此可以使用@Primary注解指定相同类型的多个Bean对象优先使用哪个Bean对象并注入到容器中

4、Bean的生命周期

4.1 Bean的生命周期

Bean的生命周期包括:

构造方法实例化、依赖注入、初始化、销毁

@Component
@Log4j2
public class LifeCycleBean {

    public LifeCycleBean() {
        log.info("LifeCycleBean构造方法执行");
    }

    @Autowired
    public void autowire(I18nMsgService i18nMsgService) {
        System.out.println(i18nMsgService.toString());
        log.info("LifeCycleBean依赖注入对象");
    }

    @PostConstruct
    public void init() {
        log.info("LifeCycleBean初始化");
    }

    @PreDestroy
    public void destroy() {
        log.info("LifeCycleBean销毁方法");
    }

}

用@Component注解将LifeCycleBean对象注入到容器中,构造方法,用@Autowired注解依赖注入对象,用@PostConstruct注解实现初始化方法,用@PreDestroy注解实现销毁方法,方法的入参可以传入容器中的Bean对象

在这里插入图片描述

Bean的生命周期顺序是执行构造方法实例化、依赖注入方法、初始化方法、销毁方法

和Bean的生命周期相关的有Bean的后置处理器

@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if("lifeCycleBean".equals(beanName)) {
            System.out.println(beanName + "对象构造方法执行之前(实例化之前)");
        }
        // 修改返回的对象,如果返回null则保持原对象不变
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if("lifeCycleBean".equals(beanName)) {
            System.out.println(beanName + "对象构造器方法执行之后(实例化之后)");
        }
        // 如果返回false则会跳过依赖注入阶段
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if("lifeCycleBean".equals(beanName)) {
            System.out.println(beanName + "对象依赖注入执行,解析@Autowired、@Resource、@Value");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if("lifeCycleBean".equals(beanName)) {
            System.out.println(beanName + "对象的初始化方法之前执行,解析@PostConstruct, @ConfigurationProperties注解");
        }
        // 修改返回的对象,如果返回null则保持原对象不变
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if("lifeCycleBean".equals(beanName)) {
            System.out.println(beanName + "对象的初始化方法之后执行,可以创建代理对象用来增强");
        }
        // 修改返回的对象,如果返回null则保持原对象不变
        return null;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if("lifeCycleBean".equals(beanName)) {
            System.out.println(beanName + "对象的销毁方法之前执行");
        }
    }

}

InstantiationAwareBeanPostProcessor和DestructionAwareBeanPostProcessor接口都继承了BeanPostProcessor接口

重写了实例化之前和之后的方法,重写了依赖注入之前的方法,重写了初始化之前和之后的方法,重写了销毁之前的方法

在这里插入图片描述

在LifeCycleBean对象的构造方法之前和之后分别打印,在依赖注入方法之前打印,在初始化方法之前和之后分别打印,在销毁方法之前打印

4.2 模板方法模式

模拟getBean方法,bean的生命周期中后置处理器用到模板方法模式

public class MyBeanFactory {
    @Test
    public void f1() {
        MyBeanFactory myBeanFactory = new MyBeanFactory();
        myBeanFactory.addBeanPostProcessor(bean -> System.out.println("bean后置处理器解析@Autowired注解"));
        myBeanFactory.addBeanPostProcessor(bean -> System.out.println("bean后置处理器解析@Resource注解"));
        Object bean = myBeanFactory.getBean();
        System.out.println("bean = " + bean);
    }

    public Object getBean() {
        Object bean = new Object();
        System.out.println("bean构造方法执行");
        System.out.println("bean依赖注入执行");
        // 抽象方法模式中变化的部分放在接口的方法上
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
            beanPostProcessor.inject(bean);
        }
        System.out.println("bean初始化方法执行");
        System.out.println("bean销毁方法执行");
        return bean;
    }

    // 持有变化部分的接口集合
    private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        beanPostProcessorList.add(beanPostProcessor);
    }

    public interface BeanPostProcessor {
        public abstract void inject(Object bean);
    }

}

模板方法模式是将变化的部分封装成一个接口或者抽象类,包含抽象方法,持有接口或者抽象类的List集合,用add方法新增持有的接口或者抽象类

在这里插入图片描述

模板方法模式可以执行Bean的生命周期

5、Bean的后置处理器

static class Bean1 {

    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        System.out.println("@Autowired注解生效");
        this.bean2 = bean2;
    }

    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        System.out.println("@Resource注解生效");
        this.bean3 = bean3;
    }

    @Autowired
    public void getServerPort(@Value("${server.port}") String port) {
        System.out.println("@Value生效,port = " + port);
    }

    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct注解生效");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("@PreDestroy注解生效");
    }

}

static class Bean2 {

}

static class Bean3 {

}

定义Bean1、Bean2、Bean3等Bean对象,其中@Autowired修改的方法入参可以传入容器中的Bean对象,如果是字符串就用@Value注入

// GenericApplicationContext对象注册Bean对象
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean("bean1", Bean1.class);
genericApplicationContext.registerBean("bean2", Bean2.class);
genericApplicationContext.registerBean("bean3", Bean3.class);

// 注册后置处理器对象
// 设置@Value注入的对象
genericApplicationContext.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 解析@Autowired @Value注解
genericApplicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class);
// 解析@Resource @PostConstruct @PreDestroy注解
genericApplicationContext.registerBean(CommonAnnotationBeanPostProcessor.class);
// 解析@ConfigurationProperties注解
ConfigurationPropertiesBindingPostProcessor.register(genericApplicationContext.getDefaultListableBeanFactory());

// 初始化容器
genericApplicationContext.refresh();

// 销毁容器
genericApplicationContext.close();

GenericApplicationContext容器对象可以通过registerBean方法注册Bean对象,可以注册BeanPostProcessor后置处理器对象,可以通过refresh方法初始化容器,通过close方法销毁容器

在这里插入图片描述

先处理@Resource的后置处理器,然后处理@Autowired的后置处理器,因为@Resource的后置处理器的优先级更高

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值