Spring底层原理(二)
Spring底层原理(二)
BeanFactory
的实现
//创建BeanFactory对象
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//注册Bean定义对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SpringConfig.class).setScope("singleton").getBeanDefinition();
factory.registerBeanDefinition("config",beanDefinition);
for (String name : factory.getBeanDefinitionNames()) {System.out.println(name);
}
使用AnnotationConfigUtils
为容器添加后置处理器
//给BeanFactory添加一些常用的后置处理器,对BeanFactory功能进行增强
AnnotationConfigUtils.registerAnnotationConfigProcessors(factory);
Spring自带的后置处理器
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
-
internalConfigurationAnnotationProcessor
:对@Configuration
与@Bean
注解进行解析处理,为BeanFactory
后置处理器 -
internalAutowiredAnnotationProcessor
:对@Autowired
注解进行解析处理,是Bean后置处理器
-
internalCommonAnnotationProcessor
:对@Resource
注解进行解析处理,是Bean后置处理器
执行BeanFactory
后置处理器
Map<String, BeanFactoryPostProcessor> factoryPostProcessorMap = factory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor processor : factoryPostProcessorMap.values()) {processor.postProcessBeanFactory(factory);
}
- 需要调用这些后置处理器的
postProcessBeanFactory
方法,这些处理器才会生效
BeanFactory
后置处理器主要功能:补充了一些bean的定义
关联Bean
与Bean
后置处理器
factory.getBeansOfType(BeanPostProcessor.class).values().forEach(factory::addBeanPostProcessor);
Bean
后置处理器:针对Bean的生命周期的各个阶段提供拓展,例如@Autowired
@Resource
…
💡BeanFactry
中的单例对象并不是预先就创建好的,而是第一次从容器中获取时才进行创建
如何将这些单例bean预实例化呢?
factory.preInstantiateSingletons();
- 该方法将所有单例对象进行预实例化
总结
beanFactory
不会做的事
- 不会主动调用
BeanFactory
后置处理器 - 不会主动添加
Bean
后置处理器 - 不会主动初始化单例
- 不会解析
beanFactory
,也不会解析${}
与#{}
bean
后置处理器会有排序的逻辑
-
AnnotationConfigUtils
在调用registerAnnotationConfigProcessors
方法后,会自动设置一个排序比较器供后续使用//默认采用list的排序规则 public static void sort(List<?> list) {if (list.size() > 1) {list.sort(INSTANCE);} }
-
排序时会调用后置处理器的
getOrder
方法,该方法会返回一个整数,根据整数排序-
CommonAnnotationBeanPostProcessor
this.setOrder(2147483644);
-
AutowiredAnnotationBeanPostProcessor
private int order = 2147483645;
所以当
Autowired
与Resource
注解同时使用时会根据后置处理器的顺序决定谁生效 -
-
测试排序规则
ArrayList<Integer> integers = new ArrayList<>(); integers.add(2147483644); integers.add(2147483645); integers.sort(AnnotationAwareOrderComparator.INSTANCE); //[2147483644, 2147483645]
- 数字越小优先级越高,所以
@Resource
的优先级更高
- 数字越小优先级越高,所以
ApplicationContext
ClassPathApplicationContext
<?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.vmware.entity.Bean1"/><bean id="bean2" class="com.vmware.entity.Bean2"><property name="bean1" ref="bean1"/></bean>
</beans>
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {System.out.println(name);
}
- 较为经典的容器,基于
classpath
下的xml
格式的配置文件来创建
FileSystemXmlApplicationContext
FileSystemXmlApplicationContext applicationContext=new FileSystemXmlApplicationContext("D:\\spring-simple\\src\\main\\resources\\applicationContext.xml");
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {System.out.println(name);
}
- 基于磁盘路径下
xml
格式的配置文件来创建
📖它们是如何将xml
配置文件解析完成并加入到beanFactory
呢?
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader= new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
-
在
ClassPathApplicationContext
内部会自动创建一个DefaultListableBeanFactory
,然后通过XmlBeanDefinitionReader
与ClassPathResource
对配置文件进行加载并解析,然后将bean
加载到容器中 -
FileSystemXmlApplicationContext
与ClassPathApplicationContext
类似,只是通过FileSystemResource
对配置文件进行加载 -
默认情况下使用这两个容器并不会自动引入
spring
自带的后置处理器,可以使用标签<context:annotation-config/>
进行引入
AnnotationConfigApplicationContext
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
- 基于
java
配置类来创建容器 - 会自动注册
spring
自带的后置处理器到容器中,同时配置类也会被注册到容器中
AnnotationConfigServletWebServerApplicationContext
AnnotationConfigServletWebServerApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);@Configuration
static class WebConfig{//注册内嵌Web服务器工厂@Beanpublic ServletWebServerFactory servletWebServerFactory(){return new TomcatServletWebServerFactory();}//注册请求分发器@Beanpublic DispatcherServlet dispatcherServlet(){return new DispatcherServlet();}//关联WebServer与DispatcherServlet@Beanpublic DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet){return new DispatcherServletRegistrationBean(dispatcherServlet,"/");}//注册controller,bean的名称如果以/开头,则该名称即为请求路径@Bean("/hello")public Controller controller1(){return (httpServletRequest, httpServletResponse) -> {httpServletResponse.getWriter().write("hello");return null;};}}
- 这是一个经典的容器,基于
java
配置类来创建,用于web
环境