第二讲 容器实现
- BeanFactory实现的特点
- ApplicationContext 的常见实现和用法
- 内嵌容器、注册DispatcherServlet
文章目录
[007]-BeanFactory实现
在002中
ConfigurableApplicationContext
类内部组合的BeanFactory
实际类型为DefaultListableBeanFactory
,使用这个类,模拟spring 使用DefaultListableBeanFactory 类创建其他实体类对象的过程
ConfigurableApplicationContext context = SpringApplication.run(Spring01Application.class, args);
// ----class org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
System.out.println("----"+context.getClass());
// class org.springframework.beans.factory.support.DefaultListableBeanFactory
System.out.println(context.getBeanFactory().getClass());
public class TestBeaFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(即bean的一些描述信息,包含class:bean是哪个类,scope:单例还是多例,初始化、销毁方法等)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config", beanDefinition);
// 打印BeanFactory中Bean
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
@Slf4j
static class Bean1 {
public Bean1() {
log.info("构造 Bean1()");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
@Slf4j
static class Bean2 {
public Bean2() {
log.info("构造 Bean2()");
}
}
}
将 config 注册进入了 beanDefinition 容器,但是bean1,和 bean2 没有注册到容器中
给BeanFactory 添加一些常用的后处理器
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(即bean的一些描述信息,包含class:bean是哪个类,scope:单例还是多例,初始化、销毁方法等)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config", beanDefinition);
// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// 给 BeanFactory添加一些常用的后处理器,让它具备解析@Configuration、@Bean等注解的能力
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
System.out.println("--------"+ beanFactoryPostProcessor);
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// 打印BeanFactory中Bean
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
}
此时打印 bean2 是为空的,因为 @Autowired 没有起作用
// 从BeanFactory中取出Bean1,然后再从Bean1中取出它依赖的Bean2
// 可以看到结果为null,所以@Autowired注解并没有被解析
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println(bean1.getBean2());
-------
null
添加
// 要想@Autowired、@Resource等注解被解析,还要添加Bean的后处理器,可以针对Bean的生命周期的各个阶段提供扩展
// 从bean工厂中取出Bean的后处理器,并且执行这些后处理器
// BeanFactory 后处理器主要功能,补充了一些 bean 的定义
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
此时是 调用了 getBean 才创建对象
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println("bean2--" + bean1.getBean2());
使用 beanFactory.preInstantiateSingletons()后
// 准备好所有单例,get()前就把对象初始化好
beanFactory.preInstantiateSingletons();
// 从BeanFactory中取出Bean1,然后再从Bean1中取出它依赖的Bean2
// 可以看到结果为null,所以@Autowired注解并没有被解析
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println("bean2--" + bean1.getBean2());
学到了什么
A. beanFactory 不会做的事
- 不会主动调用 BeanFactory 的后处理器
- 不会主动添加Bean的后处理器
- 不会主动初始化单例
- 不会解析 BeanFactory,还不会解析 ${}, #{}
B. Bean 后处理器会有排序的逻辑
整理代码
public class TestBeaFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(即bean的一些描述信息,包含class:bean是哪个类,scope:单例还是多例,初始化、销毁方法等)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config", beanDefinition);
// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// 给 BeanFactory添加一些常用的后处理器,让它具备解析@Configuration、@Bean等注解的能力
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
System.out.println("--------"+ beanFactoryPostProcessor);
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
// Bean 后处理器,针对 bean 的生命周期的各个阶段提供扩展,例如 @Autowired @Resource
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
// 打印BeanFactory中Bean
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
// 准备好所有单例,get()前就把对象初始化好
beanFactory.preInstantiateSingletons();
// 从BeanFactory中取出Bean1,然后再从Bean1中取出它依赖的Bean2
// 可以看到结果为null,所以@Autowired注解并没有被解析
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println("bean2--" + bean1.getBean2());
}
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
@Slf4j
static class Bean1 {
@Autowired
private Bean2 bean2;
public Bean1() {
log.info("构造 Bean1()");
}
public Bean2 getBean2() {
return bean2;
}
}
@Slf4j
static class Bean2 {
public Bean2() {
log.info("构造 Bean2()");
}
}
}
bean 后处理器排序逻辑
问题:同时加@Autowired 和 @ Resource 那一段会生效
先加载的 AutowiredAnnotationBeanPostProcessor 后加载 CommonAnnotationBeanPostProcessor,所以 @Autowired 生效
@Autowired @Resource(name = "bean4") private Inter bean3;
// Bean 后处理器,针对 bean 的生命周期的各个阶段提供扩展,例如 @Autowired @Resource
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor -> {
System.out.println("----beanFactory----"+ beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
我们可以通过代码控制 生效的顺序
// Bean 后处理器,针对 bean 的生命周期的各个阶段提供扩展,例如 @Autowired @Resource
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream().sorted(beanFactory.getDependencyComparator())
.forEach(beanPostProcessor -> {
System.out.println("----beanFactory----"+ beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
增加比较器后,顺序发生了变化
通过AnnotationConfigUtils给beanFactory添加一些后处理的时候会默认设置比较器,可以对BeanPostProcessor进行排序,排序的依据是BeanPostProcessor内部的order属性,其中internalAutowiredAnnotationProcessor的order属性的值为Ordered.LOWEST_PRECEDENCE - 2,internalCommonAnnotationProcessor的order属性的值为Ordered.LOWEST_PRECEDENCE - 3。
打印结果
internalAutowiredAnnotationProcessor
:2147483645,internalCommonAnnotationProcessor
:2147483644,internalCommonAnnotationProcessor
的order
值更小,所以排序的时候会排在前面
[010] ApplicationContext 实现
- 四个重要的
ApplicationContext
接口的实现类
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
AnnnotationConfigApplicationContext
AnnotationConfigServletWebServerApplication
ClassPathXmlApplicationContext
public class TestApplication {
public static void main(String[] args) {
testClassPathXmlApplicationContext();
}
// 较为经典的容器,基于classPath 下 xml 格式的配置文件来创建
private static void testClassPathXmlApplicationContext(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring_bean.xml");
for( String name:context.getBeanDefinitionNames()){
System.out.println("--testClassPathXmlApplicationContext:" + name);
}
System.out.println("----bean2:" + context.getBean(Bean2.class).getBean1());
}
static class Bean1 {
}
static class Bean2 {
private Bean1 bean1;
public Bean1 getBean1() {
return bean1;
}
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
}
}
}
- spring配置
<?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.example.spring01.com.TestApplication.Bean1"/>
<bean id="bean2" class="com.example.spring01.com.TestApplication.Bean2">
<property name="bean1" ref="bean1"/>
</bean>
</beans>
- 输出
FileSystemXmlApplicationContext
/ 基于硬盘路径下 xml 格式的配置文件来创建
private static void testFileSystemXmlApplicationContext(){
FileSystemXmlApplicationContext context =
new FileSystemXmlApplicationContext("D:\\2022-04-22-program\\spring_heima\\spring-01\\src\\main\\resources\\Spring_bean.xml");
for( String name:context.getBeanDefinitionNames()){
System.out.println("--testFileSystemXmlApplicationContext:" + name);
}
System.out.println("----bean2:" + context.getBean(Bean2.class).getBean1());
}
也可以为相对路径
new FileSystemXmlApplicationContext("src\\main\\resources\\Spring_bean.xml");
模拟底层原理
public static void testMockClassPathAndFileSystemXmlApplicationContext() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
System.out.println("读取之前");
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println("读取之后");
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// reader.loadBeanDefinitions("spring_bean.xml");
// reader.loadBeanDefinitions(new ClassPathResource("spring_bean.xml"));
reader.loadBeanDefinitions(new FileSystemResource("src\\main\\resources\\spring_bean.xml"));
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
}
AnnotationConfigApplicationContext
//较为经典的容器,基于java配置类来创建
private static void testAnnotationConfigApplicationContext(){
// 会自动加上5个后处理器
// 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
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println(context.getBean(Bean2.class).getBean1());
}
config
@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;
}
}
<!--
把5个后处理器加进来
等价于:AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
-->
<context:annotation-config />
// 会自动加上5个后处理器
// 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
AnnotationConfigServletWebServerAppliactionContext
// 较为经典的容器,基于java配置类来创建,并且还可以用于web环境
// 模拟了 springboot web项目内嵌Tomcat的工作原理
public static void testAnnotationConfigServletWebServerApplicationContext() throws Exception {
AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
// 防止程序终止
System.in.read();
}
@Configuration
static class WebConfig {
@Bean
// 1. WebServer工厂
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
@Bean
// 2. web项目必备的DispatcherServlet
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
// 3. 将DispatcherServlet注册到WebServer上
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}
@Bean("/hello")
public Controller controller1() {
return (request, response) -> {
response.getWriter().println("hello");
return null;
};
}
}