Spring5底层原理 学习笔记(一)容器与Bean篇

笔记介绍

跟着黑马满一航老师的spring高级49讲视频
并以大佬糖果墙的文章黑马程序员Spring视频教程,全面深度讲解spring5底层原理 学习笔记作为课本所作的学习笔记

容器与Bean

BeanFactory与ApplicationContext的区别与联系

BeanFactory是什么?

父接口

BeanFactory是ApplicationContext的父接口
在这里插入图片描述

Spring的核心,ApplicationContext与BeanFactory组合

BeanFactory是Spring的核心,ApplicationContext中很多功能都是通过与BeanFactory组合实现的
ApplicationContext中包含了成员变量BeanFactory的实现类,很多功能是通过调用这个实现类来实现的
在Springboot启动类中返回的具体实现类是AnnotationConfigServletWebserverApplicationContext该类继承了GenericApplicationContext
在这里插入图片描述
同时可以在GenericApplicationContext中找到ApplicationContext的实现类所作为的成员变量
在这里插入图片描述

BeanFactory的功能

基本功能

在这里插入图片描述

容器

继承DefaultSingletonBeanRegistry
成员变量Map<String, Object> singletonObjects;

前面提到SpringBoot启动程序返回的ApplicationContext是AnnotationConfigServletWebServerApplicationContext,查看它的成员变量BeanFactory的实现类是DefaultListableBeanFactory
在这里插入图片描述
通过DefaultListableBeanFactory的类图可以看到它有一个父类叫做DefaultSingletonBeanRegistry
在这里插入图片描述

查看这个类,可以看到有一个Map<String, Object>类型的成员变量singletonObjects,单例就被管理在这个Map内。

ApplicationContext比BeanFactory多了什么

Application多实现了4个接口
在这里插入图片描述

MessageSource

国际化多语言
在resources目录下创建四个文件messages.propertes、messages_en.properties、messages_ja.properties、messages_zh.properties,然后分别在四个文件里面定义同名的key,比如在message_en.properties中定义hi=hello,在messages_ja.propertes中定义hi=こんにちは,在messages_zh中定义hi=你好,这样在代码中就可以根据这个key hi和不同的语言类型获取不同的value了。

System.out.println(context.getMessage("hi", null, Locale.CHINA));
System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
System.out.println(context.getMessage("hi", null, Locale.JAPANESE));

在这里插入图片描述

EnvironmentCapable

环境变量相关
获取系统环境变量中的java_home和项目的application.yml中的server.port属性

System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
ResourcePatternResolver

源路径匹配
例1:获取类路径下的messages开头的配置文件

Resource[] resources = context.getResources("classpath:messages*.properties");
for (Resource resource : resources) {
    System.out.println(resource);
}

在这里插入图片描述

例2:获取spring相关jar包中的spring.factories配置文件

resources = context.getResources("classpath*:META-INF/spring.factories");
for (Resource resource : resources) {
    System.out.println(resource);
}

在这里插入图片描述

ApplicationEventPublisher

发布事件对象

  • 事件类对象
    定义一个类继承ApplicationEvent
  • 监听器对象
    监听对象需要交给Spring容器管理,即使用@Component注解
    定义一个方法,这个方法使用注解@EventListener
    并且这个方法的入参是定义的事件类型
  • 启动事件
    调用context.publishEvent(new 指定的事件类型);

容器实现

BeanFactory的实现类DefaultListableBeanFactory

一个很重要的实现类DefaultListableBeanFactory,该类具有什么功能呢
定义了一个Config类,并且用@Configuration标注了,这个类里面也使用@Bean注解返回了Bean1和Bean2

public static void main(String[] args) {
	DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(log::debug);
}

	@Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    @Data
    @Slf4j
    static class Bean1 {
        public Bean1() {
            log.debug("Create bean1");
        }
        @Autowired
        private Bean2 bean2;
    }

    @Slf4j
    static class Bean2 {
        public Bean2() {
            log.debug("Create bean2");
        }
    }

一开始直接创建DefaultListableBeanFactory,此时容器中肯定是没有config类的,获取所有的BeanDefinition打印,结果是空的。
因此需要手动通过创建BeanDefinition(bean定义)并注入到容器中。

public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(log::debug);
    }

这时候可以看到控制台打印出现了myConfig
在这里插入图片描述
但是bean1和bean2还是没有。这是因为DefaultListableBeanFactory的功能比较基础,如果需要解析注解还需要后置处理器来帮助完成。

public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        // 添加解析注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(log::debug);
}

在这里插入图片描述
打印结果多了很多Processor,但是仍然没有bean1和bean2,这是因为添加了后置处理器还需要执行它们

public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        // 添加解析注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

		// 遍历这些后置处理器并执行
    	beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            log.debug(beanFactoryPostProcessor.toString());
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(log::debug);
}
16:56:12.012 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
16:56:12.031 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
16:56:12.034 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.annotation.ConfigurationClassPostProcessor@2cb4c3ab
16:56:12.185 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.event.EventListenerMethodProcessor@15b3e5b
16:56:12.190 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - myConfig
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.annotation.internalConfigurationAnnotationProcessor
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.annotation.internalAutowiredAnnotationProcessor
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.annotation.internalCommonAnnotationProcessor
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.event.internalEventListenerProcessor
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - org.springframework.context.event.internalEventListenerFactory
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - bean1
16:56:12.199 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - bean2

可以看到bean1和bean2了

这时候如果想看看bean1的成员变量bean2会是什么情况呢?

public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        // 添加解析注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

		// 遍历这些后置处理器并执行
    	beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            log.debug(beanFactoryPostProcessor.toString());
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });
		// 打印bean2
		Bean2 bean2 = beanFactory.getBean(Bean1.class).getBean2();
        log.debug("bean2 ========> {}", bean2 == null ? null : bean2.toString());
}

控制台输出

17:19:12.124 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - bean2 ========> null

这时候bean2为null,说明autowired注解没有生效。这是因为我们只执行了BeanFactory的后置处理器,并没有执行Bean的后置处理器,像@Autowired这些跟Bean生命周期相关的后置处理器是Bean后置处理器,因此执行Bean的后置处理器再打印看看

public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        // 添加解析注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

		// 遍历这些后置处理器并执行
    	beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            log.debug(beanFactoryPostProcessor.toString());
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });
        
		// 执行BeanPostProcessor
		beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
		// 分割线
		log.debug("===================================================================");
		// 打印bean2
		Bean2 bean2 = beanFactory.getBean(Bean1.class).getBean2();
        log.debug("bean2 ========> {}", bean2 == null ? null : bean2.toString());
}

控制台

17:26:30.785 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
17:26:30.806 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
17:26:30.952 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
17:26:30.953 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
17:26:30.954 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
17:26:30.958 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - ===================================================================
17:26:30.958 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
17:26:30.959 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myConfig'
17:26:30.972 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication$Bean1 - Create bean1
17:26:30.979 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
17:26:30.980 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication$Bean2 - Create bean2
17:26:30.981 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - bean2 ========> com.ysatnaf.spring_learning.SpringLearningApplication$Bean2@38364841

这时候bean2不为null了
并且观察分割线,不难发现bean1和bean2的构造方法打印"Create bean1""Create bean2"都在分割线之后,说明容器中的实例对象都是懒加载的,如果需要提前将这些对象实例化好,需要调用preInstantiateSingleton方法

public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        // 添加解析注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

		// 遍历这些后置处理器并执行
    	beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            log.debug(beanFactoryPostProcessor.toString());
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });
        
		// 执行BeanPostProcessor
		beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
		// 提前实例化
		beanFactory.preInstantiateSingletons();
		// 分割线
		log.debug("===================================================================");
		// 打印bean2
		Bean2 bean2 = beanFactory.getBean(Bean1.class).getBean2();
        log.debug("bean2 ========> {}", bean2 == null ? null : bean2.toString());
}

控制台

17:28:11.772 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
17:28:11.794 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
17:28:11.938 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
17:28:11.939 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
17:28:11.940 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
17:28:11.944 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myConfig'
17:28:11.952 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
17:28:11.969 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication$Bean1 - Create bean1
17:28:11.978 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
17:28:11.979 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication$Bean2 - Create bean2
17:28:11.985 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - ===================================================================
17:28:11.986 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - bean2 ========> com.ysatnaf.spring_learning.SpringLearningApplication$Bean2@6b1274d2

Process finished with exit code 0

这时候create时机跑到分割线上方了

  • 总结
    • BeanFactory不会自动执行BeanFactoryPostProcessor
    • BeanFactory不会自动执行BeanPostProcessor
    • BeanFactory不会自动实例化对象
    • BeanFactory不会解析beanFactory,#{}和${}

BeanFactory的后置处理器排序

已知自动装配的时候可以使用@Autowired或者@Resource
那么如果有一个接口有两个实现类,同时使用@Autowired注入实现类A,使用@Resource注入实现类B,那么最终程序会选择哪个实现类呢?
创建一个接口Inter,并添加两个Inter的实现类Bean3和Bean4,如果在Bean1中自动注入一个Inter,同时使用@Autowired根据名字注入bean3,使用@Resource(name = “bean4”)注入Bean4,那么会注入的是哪个呢

@Configuration
static class Config {
    @Bean
    public Bean1 bean1() {
        return new Bean1();
    }

    @Bean
    public Bean2 bean2() {
        return new Bean2();
    }

    @Bean
    public Bean3 bean3() {
        return new Bean3();
    }

    @Bean
    public Bean4 bean4() {
        return new Bean4();
    }
}

interface Inter {

}

static class Bean3 implements Inter {

}

static class Bean4 implements Inter {

}

@Data
@Slf4j
static class Bean1 {
    public Bean1() {
        log.debug("Create bean1");
    }
    @Autowired
    private Bean2 bean2;

    @Autowired
    @Resource(name = "bean4")
    private Inter bean3;
}

    public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("myConfig", beanDefinition);

        // 添加解析注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

       beanFactory.getBeansOfType(BeanPostProcessor.class).values()
                .forEach(beanPostProcessor -> {
                    log.debug("beanPostProcessor ============================> {}", beanPostProcessor.toString());
                    beanFactory.addBeanPostProcessor(beanPostProcessor);
                });

        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
        
        Inter inner= beanFactory.getBean(Bean1.class).getBean3();
        log.debug("inner ========> {}", inner == null ? null : inner.toString());
19:22:36.039 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - beanPostProcessor ============================> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@3d8314f0
19:22:36.040 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - beanPostProcessor ============================> org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@3bd94634
19:22:36.078 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - inner ========> com.ysatnaf.spring_learning.SpringLearningApplication$Bean3@6b1274d2
Process finished with exit code 0


此时打印bean3,控制台输出的是bean3,并且发现AutowiredAnnotationBeanPostProcessor的顺序出现在CommonAnnotationBeanPostProcessor的前面,是不是跟这两个顺序有关系呢?
对他们的加载顺序进行更改看看

beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
                .sorted(beanFactory.getDependencyComparator())
                .forEach(beanFactory::addBeanPostProcessor);
19:23:33.104 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - beanPostProcessor ============================> org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@2df32bf7
19:23:33.104 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - beanPostProcessor ============================> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@58a90037
19:23:33.139 [main] DEBUG com.ysatnaf.spring_learning.SpringLearningApplication - inner ========> com.ysatnaf.spring_learning.SpringLearningApplication$Bean4@7bc1a03d
Process finished with exit code 0

这时候打印的是Bean4 ,并且CommonAnnotationBeanPostProcessor的顺序在AutowiredAnnotationBeanPostProcessor前面,果然更改了postProcessor的顺序就更改了生效的注解,那么为什么使用了beanFactory.getDependencyComparator就可以让CommonAnnotationBeanPostProcessor在AutowiredAnnotationBeanPostProcessor之前生效,那是因为在调用AnnotationConfigUtils.registerAnnotationConfigProcessors的时候,设置了按照Order进行排序的比较器
在这里插入图片描述
这个比较器会按照每一个后置处理器的order值对后置处理器的生效顺序进行排序,因为CommonAnnotationBeanPostProcessor的order值为2147483644,小于AutowiredAnnotationBeanPostProcessor的order值2147483645,所以CommonAnnotationBeanPostProcessor在这个排序条件下优先生效了

ApplicationContext的实现类

ClassPathXmlApplicationContext和FileSystemXmlApplicationContext

这两个都是读取并解析xml配置文件加载bean的

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="bean1" class="com.ysatnaf.spring_learning.ApplicationContextImpl.Bean1"/>
    <bean id="bean2" class="com.ysatnaf.spring_learning.ApplicationContextImpl.Bean2">
        <property name="bean1" ref="bean1"/>
    </bean>
</beans>
public class ApplicationContextImpl {
    public static void main(String[] args) {
        testClassPathXmlApplicationContext();
        testFileSystemXmlApplicationContext();
    }

    private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application_impl.xml");
        Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);
    }

    private static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("D:\\IdeaProjects\\spring_learning\\src\\main\\resources\\application_impl.xml");
        Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);
    }

    @Data
    static class Bean1 {
    }

    @Data
    static class Bean2 {
        private Bean1 bean1;
    }
}

这两个都可以读取xml文件是因为原理都一样,都是通过DefaultListableBeanFactory结合XmlBeanDefinitionReader读取的

private static void testDefaultListableBeanFactoryRead() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        System.out.println("Before read");
        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(System.out::println);

        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        xmlBeanDefinitionReader.loadBeanDefinitions(new ClassPathResource("application_impl.xml"));
        // 上面是ClassPath的,下面一行是FileSystem的
//        xmlBeanDefinitionReader.loadBeanDefinitions(new FileSystemResource("D:\\IdeaProjects\\spring_learning\\src\\main\\resources\\application_impl.xml"));
        System.out.println("After read");
        Arrays.stream(beanFactory.getBeanDefinitionNames()).forEach(System.out::println);
    }
AnnotationConfigApplicationContext

通过注解配置装载Bean的ApplicationContext

	private static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);
    }

	@Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(Bean1 bean1) {
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }

控制台

21:49:27.185 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@53e25b76
21:49:27.199 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
21:49:27.324 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
21:49:27.326 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
21:49:27.327 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
21:49:27.329 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
21:49:27.335 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'applicationContextImpl.Config'
21:49:27.339 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
21:49:27.349 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
21:49:27.352 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'bean2' via factory method to bean named 'bean1'
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
applicationContextImpl.Config
bean1
bean2

可以看到除了打印了bean1和bean2,还打印出了一些后置处理器。之前的DefaultListableBeanFactory还需要手动加载这些后置处理器,而AnnotationConfigApplicationContext就不需要了。

AnnotationConfigServletWebServerApplicationContext

该ApplicationContext基于Java配置类,并应用于web环境
这个配置类需要三个bean

  1. 内置的ServletWebServer
  2. DispacherServlet
  3. 结合1和2的DispatcherServletRegistrationBean
private static void testAnnotationConfigServletWebServerApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
    }

    @Configuration
    static class WebConfig {
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        @Bean
        public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        @Bean("/hello")
        public Controller controller1() {
            return (request, response) -> {
                response.getWriter().println("Hello AnnotationConfigServletWebServerApplicationContext.");
                return null;
            };
        }
    }

成功访问
在这里插入图片描述

Bean的生命周期

bean的生命周期包括

  1. 构建。构造器
  2. 依赖注入。@Autowired、@Resource
  3. 初始化。@PostConstruct
  4. 销毁。@PreDestroy

如果加上Bean的后置处理器
后置处理器可以包括6个方法

  1. postProcessBeforeDestruction,在销毁之前
  2. postProcessBeforeInstantiation,在构建对象之前
  3. postProcessAfterInstantiation,在构建对象之后
  4. postProcessProperties,依赖注入阶段
  5. postProcessBeforeInitialization,初始化对象之前
  6. postProcessAfterInitialization,初始化对象之后

所以执行顺序是
11. postProcessBeforeInstantiation
12. 构造器
13. postProcessAfterInstantiation
14. postProcessProperties
15. 依赖注入
16. postProcessBeforeIntialization
17. @PostConstruct
18. postProcessAfterIntialization
19. postProcessBeforeDestruction
20. @PreDestroy

准备一个Bean用来测试

@Data
@Slf4j
@Component
public class LifeCycleBean {
    public LifeCycleBean() {
        log.info("=========== 构造器执行");
    }

    @Autowired
    public void autowire(@Value("${JAVA_HOME}") String javaHome) {
        log.info("=========== 依赖注入 {}", javaHome);
    }

    @PostConstruct
    public void init() {
        log.info("=========== @PostConstruct");
    }

    @PreDestroy
    public void destroy() {
        log.info("=========== @PreDestroy");
    }
}

启动Springboot并调用销毁方法

@SpringBootApplication
public class BeanLifeCycle {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(BeanLifeCycle.class);
        context.close();
    }
}

控制台打印
在这里插入图片描述

接着加入Bean的后置处理器

@Component
@Slf4j
public class LifeCycleBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.info("=========== postProcessBeforeDestruction");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.info("=========== postProcessBeforeInstantiation,返回不为null会替换原来的对象");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.info("=========== postProcessBeforeInstantiation,如果返回false会跳过依赖注入阶段");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.info("=========== postProcessProperties");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.info("=========== postProcessBeforeInitialization,这里返回的对象会替换掉原本的bean,如@PostConstruct, @ConfigurationProperties");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.info("=========== postProcessAfterInitialization,这里返回的对象会替换掉原本的bean,如代理增强");
        }
        return bean;
    }
}

控制台打印
在这里插入图片描述

常见的Bean后处理器

准备bean1,bean2,bean3三个类

@Slf4j
@Data
public class Bean1 {
    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        log.info("@Autowired 生效:{}", bean2);
        this.bean2 = bean2;
    }

    @Autowired
    public void setJava_home(@Value("${JAVA_HOME}") String java_home) {
        log.info("@Value 生效:{}", java_home);
        this.java_home = java_home;
    }

    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        log.info("@Resource 生效:{}", bean3);
        this.bean3 = bean3;
    }

    private String java_home;

    @PostConstruct
    public void init() {
        log.info("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy() {
        log.info("@PreDestroy 生效");
    }

}

public class Bean2 {

}

public class Bean3 {

}

使用GenericApplicationContext进行测试,因为该类的功能相对比较干净,并且可以调用refresh方法执行后处理器

public class CommonBeanPostProcessor {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);

        // refresh方法会去执行所有的BeanFactoryPostProcessor, BeanPostProcessor, 实例化所有单例
        context.refresh();
        context.close();
    }
}

AutowiredAnnotationBeanPostProcessor和 CommonAnnotationBeanPostProcessor

此时控制台不会打印任何Bean1相关生命周期的内容,说明Bean1的注解没有被解析到
需要添加后处理器AutowiredAnnotationBeanPostProcessor解析@Autowired,@Value
添加后处理器CommonAnnotationBeanPostProcessor解析@Resource,@PostConstruct, @PreDestroy

public class CommonBeanPostProcessor {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);

        // 设置解析@Value的解析器
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 解析@Autowired和@Value
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 解析@Resource,@PostConstruct, @PreDestroy
        context.registerBean(CommonAnnotationBeanPostProcessor.class);

        // refresh方法会去执行所有的BeanFactoryPostProcessor, BeanPostProcessor, 实例化所有单例
        context.refresh();
        context.close();
    }
}

控制台
在这里插入图片描述

ConfigurationPropertiesBindingPostProcessor

用于解析@ConfigurationProperties注解

AutowiredAnnotationBeanPostProcessor分析

总体流程

该后处理器是在postProcessorProperties方法中实现了对@Autowired和@Value的解析
第一步找出标注了@Auwired的成员变量、方法
第二步对属性进行依赖注入

public class AutowiredAnnotationBeanPostProcessorTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2());
        beanFactory.registerSingleton("bean3", new Bean3());

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        // 设置解析@Value的解析器
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 设置可以解析占位符的解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        // 把beanFactory提供给后处理器
        processor.setBeanFactory(beanFactory);
        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
        // 调用后处理器的postProcessProperties方法
        processor.postProcessProperties(null, bean1, "bean1");
        System.out.println(bean1);
    }
}

在这里插入图片描述
查看postProcessProperties方法内部
在这里插入图片描述
debug可以看到查找到两个@Autowired注解标注的
在这里插入图片描述

如果找到需要注入的对象
  • 属性
    1. 把加了@Autowired属性的name拿到
    2. 根据name查询拿到属性Field
    3. 把这个Filed封装成DependencyDescriptor
    4. 调用Bean工厂的doResolveDependency从bean工厂中按照类型找到对应的实例
    5. 通过反射赋值
      在这里插入图片描述
  • 方法
    1. 通过@Autowired注解拿到方法名
    2. 通过反射根据方法名拿到对应的方法对象
    3. 根据参数位置拿到参数的类型
    4. 把这个参数包装成DependecyDescriptor对象
    5. 调用bean工厂的doResolveDependency方法找到对应的实例
    6. 通过反射把找到的实例进行赋值
      在这里插入图片描述

BeanFactory后处理器

  • ConfigurationClassPostProcessor可以解析@ComponentScan, @Bean, @Import, @ImportResource等。
  • MapperScannerConfigurer用于扫描Mybatis的各种Mapper

模拟ComponentScan功能

准备Config类,标注@ComponentScan注解

@ComponentScan(basePackages = "com.ysatnaf.spring_learning.bean_post_processor.configuration_class_post_processor.beans")
public class Config {

}

准备Bean1,2,3放在包com.ysatnaf.spring_learning.bean_post_processor.configuration_class_post_processor.beans
给Bean1添加注解@Component,Bean2添加注解@Controller,Bean3不添加

使用GenericApplicationContext进行测试

public class ComponentScanTest {
    public static void main(String[] args) {
        // 模拟ConfigurationClassConfigProcessor
        GenericApplicationContext context = new GenericApplicationContext();

        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);

        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        if (componentScan != null) {
            String[] basePackages = componentScan.basePackages();
            Arrays.stream(basePackages).forEach(basePackage -> {
                // 转换路径从com.xxx.xxx形式转成 classpath*:com/xxx/xxx/**/*.class形式
                String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";
                try {
                    // 获取resources
                    Resource[] resources = context.getResources(path);
                    for (Resource resource : resources) {
                        // 使用CachingMetadataReaderFactory将resource转换成MetadataReader以便于对其信息进行操作
                        MetadataReader metadataReader = factory.getMetadataReader(resource);
                        System.out.println(metadataReader.getClassMetadata().getClassName());
                        System.out.println("是否有@Component:" + metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
                        System.out.println("是否有@Component派生:" + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }
}

进一步改造上面的代码,创建一个实现BeanDefinitionRegistryPostProcessor的自定义后处理器
实现postProcessBeanDefinitionRegistry方法

public class ComponentScanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);

        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        if (componentScan != null) {
            String[] basePackages = componentScan.basePackages();
            Arrays.stream(basePackages).forEach(basePackage -> {
                // 转换路径从com.xxx.xxx形式转成 classpath*:com/xxx/xxx/**/*.class形式
                String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";
                try {
                    // 获取resources
                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                    AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
                    for (Resource resource : resources) {
                        // 使用CachingMetadataReaderFactory将resource转换成MetadataReader以便于对其信息进行操作
                        MetadataReader metadataReader = factory.getMetadataReader(resource);
//                        System.out.println(metadataReader.getClassMetadata().getClassName());
//                        System.out.println("是否有@Component:" + metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
//                        System.out.println("是否有@Component派生:" + metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
                        // 直接或间接标注了@Component的类,加入到Spring容器管理
                        if (metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName())
                                || metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())) {
                            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                                    .genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();

                            String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
                            registry.registerBeanDefinition(beanName, beanDefinition);
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }
}

测试代码

public class ComponentScanTest {
    public static void main(String[] args) {
        // 模拟ConfigurationClassConfigProcessor
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(Config.class);
        context.registerBean(ComponentScanPostProcessor.class);

        context.refresh();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }
}

控制台
在这里插入图片描述

模拟@Bean

拿到Config类标注了@Bean方法的信息
将这些方法设置成为工厂方法

public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 直接写死拿到Config类的注解信息
        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
        MetadataReader metadataReader = null;
        try {
            metadataReader = cachingMetadataReaderFactory.getMetadataReader(new ClassPathResource("com/ysatnaf/spring_learning/bean_factory_post_processor/configuration_class_post_processor/Config.class"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata annotatedMethod : annotatedMethods) {

            String initMethodName = (String) annotatedMethod.getAnnotationAttributes(Bean.class.getName()).get("initMethod");
            System.out.println(initMethodName);
            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition()
                    .setFactoryMethodOnBean(annotatedMethod.getMethodName(), Config.class.getName())
                    .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR )
                    .setInitMethodName(initMethodName)
                    .getBeanDefinition();

            registry.registerBeanDefinition(annotatedMethod.getMethodName(), beanDefinition);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

模拟Mapper扫描

Mapper使用@Bean单个添加的方式

通过MapperFactoryBean对象

@Bean
public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) {
        MapperFactoryBean<Mapper1> mapperFactoryBean = new MapperFactoryBean<>(Mapper1.class);
        mapperFactoryBean.setSqlSessionFactory(sqlSessionFactory);
        return mapperFactoryBean;
    }
通过自定义后处理器批量添加
public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            Resource[] resources = resolver.getResources("classpath:com/ysatnaf/spring_learning/bean_factory_post_processor/configuration_class_post_processor/mapper/**/*.class");
            CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
            AnnotationBeanNameGenerator nameGenerator = new AnnotationBeanNameGenerator();
            for (Resource resource : resources) {
                MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                if (classMetadata.isInterface()) {
                    // 创建MapperFactoryBean的BeanDefinition,构造参数需要SqlSessionFactory
                    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                            .addConstructorArgValue(classMetadata.getClassName())
                            .setAutowireMode(AbstractAutowireCapableBeanFactory.AUTOWIRE_BY_TYPE)
                            .getBeanDefinition();

                    // 另外生成Mapper的BeanDefinition,是为了生成BeanName
                    AbstractBeanDefinition nameBeanDefinition = BeanDefinitionBuilder
                            .genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
                    String beanName = nameGenerator.generateBeanName(nameBeanDefinition, registry);
                    registry.registerBeanDefinition(beanName, beanDefinition);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

Aware和InitializingBean接口

  • Aware接口的作用就是注入注入一些容器相关的信息
    • BeanNameAware,注入bean的名字
    • BeanFactoryAware,注入BeanFactory容器
    • ApplicationContextAware,注入ApplicationContext容器
    • EmbeddedValueResolverAware ,注入解析器,解析${}
  • InitializingBean接口处理初始化

与后处理器的区别就是这些是内置的不会失效,而后处理器的功能是扩展的,可能会失效

@Autowired失效分析

准备类MyConfig1

@Slf4j
@Configuration
public class MyConfig1 {

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        log.debug("注入ApplicationContext");
    }

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

    @Bean
    public BeanFactoryPostProcessor postProcessor() {
        return beanFactory -> log.debug("@Bean 注入BeanFactoryPostProcessor");
    }
}

加载MyConfig1查看执行情况

public class AwareFailTest {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("myConfig1", MyConfig1.class);
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        context.registerBean(ConfigurationClassPostProcessor.class);

        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }
}

在添加BeanFactoryPostProcessor之前,控制台是可以打印依赖注入和初始化过程的,但是在通过@Bean的方式增加了BeanFactoryPostProcessor之后,就只会打印"@Bean 注入BeanFactoryPostProcessor"了
此时@Autowired和@PostConstruct失效了
这跟生命周期有关

  1. Spring会先执行BeanFactoryPostProcessor
  2. 然后注册BeanPostProcessor
  3. 创建和初始化对象
    1. 依赖注入扩展(@Autowired)
    2. 初始化扩展(@PostConstruct)
    3. 执行Aware和InitializingBean
    4. 创建完成

这时候由于Java配置类中包括了BeanFactoryPostProcessor,要执行BeanFactoryPostProcessor就要先创建好Java配置类,使得第3步提前了

  1. 创建和初始化对象
    1. 依赖注入扩展(@Autowired)
    2. 初始化扩展(@PostConstruct)
    3. 执行Aware和InitializingBean
    4. 创建完成
  2. 执行BeanFactoryPostProcessor
  3. 注册BeanPostProcessor
    在创建和初始化对象的时候依赖注入扩展@Autowired和初始化的扩展@PostConstruct功能由于需要BeanPostProcessor的支持,但是现在注册BeanPostProcessor还没执行,所以导致了@Autowired和@PostConstruct失效
    也就是说如果Java配置类没有BeanPostProcessor的话,执行顺序如下
ApplicationContext BeanFactoryPostProcessor BeanPostProcessor Java配置类 1. 执行BeanFactoryPostProcessor 2. 注册BeanPostProcessor 3. 创建和初始化Java配置类 3.1 依赖注入扩展(@Autowired和@Value等) 3.2 初始化扩展(@PostConstruct) 3.3 执行Aware和InitializingBean 4. 创建完成 ApplicationContext BeanFactoryPostProcessor BeanPostProcessor Java配置类

在配置类有了BeanPostProcessor后,执行顺序变为

ApplicationContext BeanFactoryPostProcessor BeanPostProcessor Java配置类 1. 创建和初始化Java配置类 1.1 执行Aware和InitializingBean 2. 创建完成 3. 执行BeanFactoryPostProcessor 4. 注册BeanPostProcessor ApplicationContext BeanFactoryPostProcessor BeanPostProcessor Java配置类

初始化与销毁

Spring提供了三种初始化相关方法,按照执行顺序分别是

  1. @PostConstruct注解标注的方法
  2. 接口InitializingBean的afterPropertiesSet方法
  3. @Bean(initMethod=“”)指定的方法

同样的提供了三种跟销毁相关的方法,按照执行顺序分别是

  1. @PreDestroy注解标注的方法
  2. 接口DisposableBean的destroy方法
  3. @Bean(destroyMethod=“”)指定的方法

Scope

Singleton注入其他scope不生效的情况分析与4种解决方式

在一个Singleton的类A中注入一个成员变量B,B的Scope是prototype,这时候多次调用A的getB方法,返回的对象始终是一个
这是因为A是单例的,所以依赖注入过程只发生过一次,所以A里面的B永远是一开始注入的那个B

  • 解决方法
    • 在成员变量B上使用@Lazy注解(每次通过代理生成不同实例对象)
    • 在B的@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)(每次通过代理生成不同实例对象)
    • 使用ObjectFactory返回
    • 在B中注入ApplicationContext,使用ApplicationContext.getBean返回
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值