Spring原理(1)——容器
容器接口
BeanFactory
-
是ApplicationContext的父接口,所有ApplicationContext的实现都组合了BeanFactory。
-
BeanFactory才是Spring的核心容器。
从BeanFactory提供的方法来看,主要是从容器中获取Bean。实际上控制反转,依赖注入以及Bean的生命周期管理,都由它的实现类提供。如下展示了BeanFactory其中一个实现类DefaultListableBeanFactory
的继承关系。
可以看到,它的继承路线上有一个DefaultSingletonBeanRegistry
类,这个类我们打开可以看到如下代码段,其中singletonObjects
对象正是容器中所有单例对象被保存的地方。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { /** Cache of singleton objects: bean name to bean instance. */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 保存了所有的单例对象 /** Cache of singleton factories: bean name to ObjectFactory. */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); ... }
ApplicationContext
ApplicationContext继承自多个接口,因此提供了多种能力,具体提供的能力如下代码所示。
@SpringBootApplication public class SsmpApplication { public static void main(String[] args) throws IOException { final ConfigurableApplicationContext context = SpringApplication.run(SsmpApplication.class, args); // MessageSource接口提供的功能,实现国际化能力 context.getMessage("hi", null, Locale.CHINA); context.getMessage("hi", null, Locale.US); // ResourcePatternResolver接口提供的能力,实现读取资源文件的能力 final Resource[] resources = context.getResources("classpath*:spring.factories"); // EnvironmentCapable接口提供的能力,实现获取环境参数的能力,可以获取环境变量、配置等 final String java_home = context.getEnvironment().getProperty("java_home"); final String port = context.getEnvironment().getProperty("server.port"); // ApplicationEventPublisher提供的能力,可以发送事件,实现解耦 context.publishEvent(new MyEvent(context)); } public static class MyEvent extends ApplicationEvent { public MyEvent(Object source) { super(source); } } }
容器实现
BeanFactory实现
以下代码的注释中展示了BeanFactory是如何注册Bean的,以及注册后如何进行后处理的。
点击查看代码
package com.leo.ssmp; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Collection; @SpringBootApplication @Slf4j public class SsmpApplication { public static void main(String[] args) { // 将MyConfig类注册到BeanFactory中,由BeanFactory管理Bean的生成,销毁 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); final BeanDefinition configDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyConfig.class) .setScope("singleton") .getBeanDefinition(); beanFactory.registerBeanDefinition("config", configDefinition); // 向BeanFactory上注册一些后处理器,这些后处理器可以解析@Configuration和@Bean这些注解 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory); // BeanFactory后处理器,执行后处理操作,处理@Configuration注解,将bean1和bean2生成出来 final Collection<BeanFactoryPostProcessor> beanFactoryPostProcessors = beanFactory.getBeansOfType( BeanFactoryPostProcessor.class).values(); log.info("---------------BeanFactory后处理器------------------"); beanFactoryPostProcessors.forEach(beanFactoryPostProcessor -> log.info(beanFactoryPostProcessor.toString())); beanFactoryPostProcessors.forEach(beanFactoryPostProcessor -> { beanFactoryPostProcessor.postProcessBeanFactory(beanFactory); }); log.info("---------------BeanFactory后处理器------------------"); // Bean后处理器,针对Bean的生命周期的各个阶段做扩展,例如@Autowired @Resource, // 这样才能在生成bean1后,向bean1中注入bean2 final Collection<BeanPostProcessor> beanPostProcessors = beanFactory.getBeansOfType(BeanPostProcessor.class) .values(); log.info("----------------Bean后处理器-----------------"); beanPostProcessors.forEach(beanPostProcessor -> log.info(beanPostProcessor.toString())); beanPostProcessors.forEach(beanFactory::addBeanPostProcessor); log.info("----------------Bean后处理器-----------------"); log.info("------------------注册的所有Bean定义信息------------------"); final String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { log.info(beanDefinitionName); } log.info("------------------注册的所有Bean定义信息------------------"); final Bean1 bean1 = beanFactory.getBean(Bean1.class); log.info(bean1.getBean2().toString()); } @Configuration static class MyConfig { @Bean public Bean1 bean1() { return new Bean1(); } @Bean public Bean2 bean2() { return new Bean2(); } } static class Bean1 { @Autowired private Bean2 bean2; public Bean1() { log.info("Bean1 construct..."); } public Bean2 getBean2() { return bean2; } } static class Bean2 { public Bean2() { log.info("Bean2 construct"); } } }
以上代码的运行结果如下:
点击查看代码
10:56:43.379 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 10:56:43.395 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - ---------------BeanFactory后处理器------------------ 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.ConfigurationClassPostProcessor@724af044 10:56:43.398 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.EventListenerMethodProcessor@4678c730 10:56:43.512 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 10:56:43.513 [main] INFO com.leo.ssmp.SsmpApplication - ---------------BeanFactory后处理器------------------ 10:56:43.513 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 10:56:43.513 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - ----------------Bean后处理器----------------- 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@6385cb26 10:56:43.516 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@38364841 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ----------------Bean后处理器----------------- 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ------------------注册的所有Bean定义信息------------------ 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - config 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalConfigurationAnnotationProcessor 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalAutowiredAnnotationProcessor 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.annotation.internalCommonAnnotationProcessor 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.internalEventListenerProcessor 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - org.springframework.context.event.internalEventListenerFactory 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - bean1 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - bean2 10:56:43.517 [main] INFO com.leo.ssmp.SsmpApplication - ------------------注册的所有Bean定义信息------------------ 10:56:43.517 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1' 10:56:43.518 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config' 10:56:43.529 [main] INFO com.leo.ssmp.SsmpApplication - Bean1 construct... 10:56:43.535 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2' 10:56:43.536 [main] INFO com.leo.ssmp.SsmpApplication - Bean2 construct 10:56:43.537 [main] INFO com.leo.ssmp.SsmpApplication - com.leo.ssmp.SsmpApplication$Bean2@55040f2f Process finished with exit code 0
后处理器的执行顺序跟它们之间的排序策略有关,先执行的后处理器会生效。
ApplicationContext实现
ClassPathXmlApplicationContext
首先我们定义一个实体类
package com.leo.domain; import lombok.Data; @Data public class Book { private Integer id; private String type; private String name; private String description; }
在resources
目录下创建b01.xml
文件作为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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean id="bean1" class="com.leo.domain.Book"/> </beans>
通常我们会使用如下方式来启动和加载Spring容器
package com.leo; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; @SpringBootApplication public class SpringApplication { public static void main(String[] args) { final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "b01.xml"); } }
其内部实现如果简单的拆开来,可以用如下步骤表示,BeanFactory
是真正的容器,我们使用XmlBeanDefinitionReader
将xml中定义的bean转化成BeanDefinition
并注册到BeanFactory中。
package com.leo; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.core.io.ClassPathResource; @SpringBootApplication public class SpringApplication { public static void main(String[] args) { testClasspathXmlApplicationContext(); } private static void testClasspathXmlApplicationContext() { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); System.out.println("=======================>before"); for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) { System.out.println(beanDefinitionName); } XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(new ClassPathResource("b01.xml")); System.out.println("=======================>after"); for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) { System.out.println(beanDefinitionName); } } }
以上代码的运行结果如下:
=======================>before 14:14:13.483 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 6 bean definitions from class path resource [b01.xml] =======================>after bean1
我们会发现这是容器里只有一个Bean,但是当我们用springboot自动配置来启动容器时,会发现即使我们不定义Bean,默认也会加载一些内置的bean。那么Spring是如何加载这些内置的Bean的呢。我们可以在xml文件中加入如下配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean id="bean1" class="com.leo.ssmp.domain.Book"/> <!--这里开启了各种注解,例如Autowired--> <context:annotation-config/> </beans>
这样我们运行上面的代码时打印出来的结果如下:
=======================>before 14:14:13.483 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 6 bean definitions from class path resource [b01.xml] =======================>after 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
可以看到这时已经加载了很多处理注解和事件监听的Bean。
FileSystemXmlApplicationContext
基本原理与ClassPathXmlApplicationContext
相似,只不过这里改为从文件系统直接读取xml配置。
AnnotationConfigApplicationContext
直接通过@Configuration
注解的类来加载Bean,这种方法加载Bean时,会默认加载注解处理器这些内置的Bean。同时还会将config类也加载为Bean。
本文作者:金笔书生吕落第
本文链接:https://www.cnblogs.com/leometeor/p/17137894.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步