文章目录
笔记介绍
跟着黑马满一航老师的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
- 内置的ServletWebServer
- DispacherServlet
- 结合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的生命周期包括
- 构建。构造器
- 依赖注入。@Autowired、@Resource
- 初始化。@PostConstruct
- 销毁。@PreDestroy
如果加上Bean的后置处理器
后置处理器可以包括6个方法
- postProcessBeforeDestruction,在销毁之前
- postProcessBeforeInstantiation,在构建对象之前
- postProcessAfterInstantiation,在构建对象之后
- postProcessProperties,依赖注入阶段
- postProcessBeforeInitialization,初始化对象之前
- 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注解标注的
如果找到需要注入的对象
- 属性
- 把加了@Autowired属性的name拿到
- 根据name查询拿到属性Field
- 把这个Filed封装成DependencyDescriptor
- 调用Bean工厂的doResolveDependency从bean工厂中按照类型找到对应的实例
- 通过反射赋值
- 方法
- 通过@Autowired注解拿到方法名
- 通过反射根据方法名拿到对应的方法对象
- 根据参数位置拿到参数的类型
- 把这个参数包装成DependecyDescriptor对象
- 调用bean工厂的doResolveDependency方法找到对应的实例
- 通过反射把找到的实例进行赋值
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失效了
这跟生命周期有关
- Spring会先执行BeanFactoryPostProcessor
- 然后注册BeanPostProcessor
- 创建和初始化对象
- 依赖注入扩展(@Autowired)
- 初始化扩展(@PostConstruct)
- 执行Aware和InitializingBean
- 创建完成
这时候由于Java配置类中包括了BeanFactoryPostProcessor,要执行BeanFactoryPostProcessor就要先创建好Java配置类,使得第3步提前了
- 创建和初始化对象
- 依赖注入扩展(@Autowired)
- 初始化扩展(@PostConstruct)
- 执行Aware和InitializingBean
- 创建完成
- 执行BeanFactoryPostProcessor
- 注册BeanPostProcessor
在创建和初始化对象的时候依赖注入扩展@Autowired和初始化的扩展@PostConstruct功能由于需要BeanPostProcessor的支持,但是现在注册BeanPostProcessor还没执行,所以导致了@Autowired和@PostConstruct失效
也就是说如果Java配置类没有BeanPostProcessor的话,执行顺序如下
在配置类有了BeanPostProcessor后,执行顺序变为
初始化与销毁
Spring提供了三种初始化相关方法,按照执行顺序分别是
- @PostConstruct注解标注的方法
- 接口InitializingBean的afterPropertiesSet方法
- @Bean(initMethod=“”)指定的方法
同样的提供了三种跟销毁相关的方法,按照执行顺序分别是
- @PreDestroy注解标注的方法
- 接口DisposableBean的destroy方法
- @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返回