Spring容器源码阅读笔记

364 阅读12分钟

Spring 容器

一. 组件注册

1. 给容器中注册组件

1.1 包扫描:

  • @ComponentScan(value = ?): value里放包扫描的路径。
  • @ComponentScans: 可以配置多个扫描的包
  • excludeFilters=Filter[ ]:指定扫描包的时候按照什么规则排除哪些组件
@ComponentScan(value = "top.nnzi",excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),//按照注解排除
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {UserMapper.class}),//按照类型排除
        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {})//自定义排除规则 class里是自定义排除规则的类,实现TypeFilter接口
})
  • includeFilters=Filter[ ]:指定扫描包的时候要包含哪些组件,需将useDefaultFilters置false,使用和excludeFilters相似
@ComponentScan(value = "top.nnzi",includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},useDefaultFilters = false)

1.2 容器中注册组件

  • @Component、@Service、@Controller、@Repository、@Configuration 标注的类,主要是自己写的类
  • @Bean:主要导入第三方的包里面的组件
  • @Import:快速给容器中导入一个组件
    1. Import(类名):容器中就会自动注册这个组件,id默认是组件的全名
    2. ImportSelector:将返回值的类导入到容器
    3. ImportBeanDefinitionRegistrar:手动注册bean
@Import(MyImportSelector.class)
//MyImportSelector类实现ImportSelector接口,
//返回需要导入的组件的全类名的数组
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"top.nnzi.bean.User"};
    }
}
  • @Conditional({MyCondition.class}):标注在bean上,按照一定的条件判断,满足条件给容器中注册bean。
public class MyCondition implements Condition {

    /**
     *
     * @param context 判断条件能使用的上下文(环境)
     * @param metadata 注解信息
     * @return true为允许注册,false反之
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取ioc使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        
        //逻辑代码编写,返回判断值.

        return false;
    }
}
  • 使用Spring提供的FactoryBean(工厂bean):spring用来生产Bean到spring容器中。FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用注解即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,这时可以考虑用FactoryBean,很多开源项目在集成Spring 时都使用到FactoryBean
    1. 默认获取到的是工厂bean调用getObject创建的对象
    2. 要获取到工厂bean本身,需要给id前面加个&标识
public class UserFactoryBean implements FactoryBean<User> {

    /**
     *
     * @return 返回一个对象,该对象会被添加到容器
     * @throws Exception
     */
    @Override
    public User getObject() throws Exception {
        return new User();
    }

    /**
     *
     * @return 返回对象的类型
     */
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    /**
     *
     * @return 是否为单实例创建 true表示单实例
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}
  • @Scope():设置组件作用域
    1. prototype:多实例, ioc容器启动并不会去调用方法创建对象在容器中,而是每次获取时才会调用方法创建对象。
    2. singleton:单实例(默认值), ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是从容器中拿
  • @Lazy:bean懒加载,不是在ioc容器启动的时候创建bean,而是当bean获取的时候创建

二. 生命周期

1. bean的生命周期

1.1 bean创建--初始化--销毁的过程:

  • bean创建: 单实例:在容器启动时创建 多实例:每次获取时创建
  • bean初始化:成员变量赋值,各种增强等,对象创建完成,并赋值好,调用初始化方法
  • bean销毁 单实例:关闭容器时 多实例:容器不会管理这个bean,容器不会调用销毁方法

1.2 可以自定义初始化和销毁方法,容器在bean进行到当前声明周期的时候来调用我们自定义的初始化和销毁方法。

  • 通过@Bean 指定init-method和destroy-method

  • 通过让bean实现InitializingBean接口(定义初始化逻辑):在beanFactory将所有属性设置完成以后调用

  • 在这里插入图片描述

  • 通过让bean实现DisposableBean接口(定义销毁逻辑):在beanFactory销毁单实例对象前调用

  • 在这里插入图片描述

  • 可以使用JSR250注解:标注在方法上。 1、@PostConstructor:在bean创建完成并且属性赋值完成,来执行初始化方法 2、@PreDestroy:在容器销毁bean之前通知我们进行清理工作

  • BeanPostProcessor【接口】:bean的后置处理器:在bean初始化前后进行一些处理工作 (1) postProcessBeforeInitialization:在初始化之前进行一些工作 (2)postProcessAfterInitialization:在初始化之后进行一些工作

	public interface BeanPostProcessor {
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}
  • BeanPostProcessor的大致执行流程:

在这里插入图片描述

在这里插入图片描述

  • Spring底层对BeanPostProcess接口的使用 (1)BeanValidationPostProcessor用来实现数据校验 (2)AutowireAnnotationBeanPostProcessor,@Autowire实现 (3)ApplicationContextProcessor将容器注入到bean中 (4)InitDestroyAnnotationBeanPostProcessor会对@PostConstructor和@PreDestroy注解进行解析来达到容器的初始化和销毁方法的执行等等..

2.自动装配

  • @AutoWired:自动注入【Spring定义的】:可以标注在构造器,参数,方法,属性
  • Spring还支持使用@Resource(JSR250)和@Inject(JSR330)【java规范】
  • 自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx)自定义组件需要实现xxxAware接口;在创建对象的时候会调用接口规定的方法注入相关组件,把Spring底层的一些组件注入到自定义的bean中,xxxAware的功能都是使用xxxAwareProcessor处理的,判断实现了哪个Aware接口然后将bean转化为该类型调用set方法,将容器底层组件注入。
@Override
	@Nullable
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

  • @Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能。 (1)加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中,默认是default环境。 (2)写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能生效 (3)没有标注环境标识的bean在任何环境下都加载 运行时如何制定环境: (1)命令行参数,通过在虚拟机参数位置指定-Dspring.profiles.active=xxx来指定运行环境,标注了该环境的bean会被配置进容器中 (2)程序内指定:创建一个applicationContext ——》设置需要激活的环境,applicationContext.getEnvironment().setActiveProfiles("") ——》注册主配置类,applicationContext.register(xxx.class) ——》启动刷新容器,applicationContext.refresh();

四. AOP

五.声明式事务

  • 给方法上面标注@Transactional 标识当前方法是一个事务方法
  • @EnableTransactionManagement开启基于注解的事务管理功能
  • 配置事务管理器来控制事务
    @Bean
    public PlatformTransactionManager platformTransactionManager (DateSource dateSource) {
        return new DataSourceTransactionManager(dateSource);
    }

六. BeanPostProcessor

BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的

  1. BeanFactoryPostProcessor:beanFactory的后置处理器,在beanFactory标注初始化后调用,所以bean的定义已经保存加载到beanFactory,但是bean的实例还未创建 流程
    • ioc容器创建对象
    • invokeBeanFactoryPostProcessors(beanFactory):执行BeanFactoryPostProcessors
      • String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);找到所有postProcessor的名字执行方法
      • 在初始化创建其它组件前面执行

BeanDefinitionRegistryPostProcessor: 是BeanFactoryPostProcessor的子接口,BeanDefinitionRegistry是Bean定义信息的保存中心,BeanFactory就是按照其中保存的bean的定义信息创建bean实例的。 postProcessBeanDefinitionRegistry()方法,在所有bean定义信息将要被加载到,但是bean实例还未创建,优先于BeanFactoryPostProcess执行,可以利用其给容器中再来添加一些组件

七. ApplicationListener

ApplicationListener:监听容器中发布的事件,事件驱动模型的开发 实现ApplicationListener< E extends ApplicationEvent >接口:监听ApplicationEvent及其子类的相关事件,只要容器中有相关事件发布,我们就能监听到这个事件,如

  • ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件
  • ContextClosedEvent:关闭容器发布这个事件

或者自己发布事件:自定义发布一个事件 ioc容器.publishEvent(ApplicationEvent);

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

注解形式: @EventListener(class={}):可以在普通业务逻辑组件的方法上标注该注解来监听事件。

八. Spring容器创建过程

Spring容器的refresh()【创建刷新】

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

1. BeanFactory的创建及预准备工作

  1. prepareRefresh()刷新前的预处理
    • initPropertySources();初始化一些属性设置;子类自定义个性化属性设置方法;
    • getEnvironment().validateRequiredProperties();检验属性的合法等;
    • this.earlyApplicationEvents = new LinkedHashSet<>();保存容器中的一些早期事件
  2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 获取BeanFactory
    • refreshBeanFactory();刷新【创建】beanFactory: 在GenericApplicationContext对象构造时this.beanFactory=new DefaultListableBeanFactory();并设置标识ID
    • 通过getBeanFactory();​ 返回刚才GenericApplicationContext创建的BeanFactory【DefaultListableBeanFactory】对象
    • prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置):
      • 设置BeanFactory的类加载器、支持表达式解析器
      • 添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
      • 设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware...
      • 注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
      • 添加BeanPostProcessor【ApplicationListenerDetector】
      • 给BeanFactory中注册一些能用的组件: environment【ConfigurableEnvironment】、 systemPropertie【Map<String,Object>】、​ systemEnvironment【Map<String,Object>】
  3. postProcessBeanFactory(beanFactory);BeanFactory准备工作完成后进行的后置处理工作
    • 本身是一个空方法,子类通过重写这方法在BeanFactory创建并预准备完成以后做进一步的设置。

2.invokeBeanFactoryPostProcessors(beanFactory): 执行BeanFactoryPostProcessor的方法

BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标注初始化之后执行​ 有两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

  1. 执行invokeBeanFactoryPostProcessors方法
  2. 获取所有BeanDefinitionRegistryPostProcessor
    • 先执行实现了PriorityOrdered优先级接口的、再执行实现了Ordered的接口的、最后执行其它的
  3. 获取所有BeanFactoryPostProcessor
    • 先执行实现了PriorityOrdered优先级接口的、再执行实现了Ordered的接口的、最后执行其它的

3.registerBeanPostProcessors(beanFactory); 注册BeanPostProcessor

  1. BeanPostProcessor(Bean的后置处理器)【拦截Bean的创建过程】
  2. 不同类型的BeanPostProcessor,在Bean创建前后的执行时机是不一样的 ​ 有如下几类:
    • BeanPostProcessor
    • DestructionAwareBeanPostProcessor
    • InstantiationAwareBeanPostProcessor
    • SmartInstantiationAwareBeanPostProcessor
    • MergedBeanDefinitionPostProcessor【internalPostProcessors】
  3. 执行流程:
    • 获取所有的BeanPostProcessor; ​ 后置处理器都默认可以通过PriorityOrdered、Ordered来指定优先级
    • 先注册PriorityOrdered优先级接口的BeanPostProcessor ​ 把每一个BeanPostProcessor添加到BeanFactory中, ​ beanFactory.addBeanPostProcessor(postProcessor)
    • 再注册了实现Ordered接口的
    • 最后注册其它没有实现任何优先级接口的
    • 最终注册MergedBeanDefinitionPostProcessor类型的
    • 注册一个ApplicationListenerDetector;来在Bean创建完成后检查是否ApplicationListeneraddApplicationListener((ApplicationListener<?>) bean);

4. initMessageSource();初始化MessageSource组件(做国际化功能;消息绑定;消息解析等功能):

  1. 获取BeanFactory
  2. 看容器中是否有id为messageSource,类型是MessageSource的组件如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource,​ MessageSource:取出国际化配置文件中的某个key的值;能按照区域信息获取
  3. 把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource;调用其方法可以获得相关配置属性 beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);

5. initApplicationEventMulticaster();初始化事件派发器【多播器】

  1. 获取BeanFactory
  2. 从BeanFactory获取applicationEventMulticaster的组件
  3. 如果上一步没有配置;创建一个SimpleApplicationEventMulticaster
  4. 将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入 beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);

6. onRefresh();留给子容器(子类)

  1. 空方法,子类重写这个方法,在容器刷新的时候可以自定义逻辑

7. registerListeners();给容器中将所有项目里面的ApplicationListener注册进来

  1. 从容器中拿到所有ApplicationListener组件
  2. 将每个监听器添加到事件派发器中 ​getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  3. 派发之前步骤产生的事件

8. finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例bean

beanFactory.preInstantiateSingletons();初始化剩下的单实例bean

  1. 获取容器中的所有Bean,依次进行初始化和创建对象 ​ List beanNames = new ArrayList<>(this.beanDefinitionNames);
  2. 遍历beanNames获取bean 的定义信息; ​ RootBanDefinition bd = getMergedLocalBeanDefinition(beanName);
  3. 判断Bean不是抽象的,是单实例的,不是懒加载得 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
    • 判断是否是FactoryBean;是否是实现FactoryBean接口的Bean if (isFactoryBean(beanName))
    • 如果是,利用工厂方法创建对象getObject();
    • 不是工厂Bean,利用getBean(过程如下)(beanName);创建对象
    • 所有Bean都利用getBean创建完成以后;​ 检查所有的Bean是否是SmartInitializingSingleton接口类型的,如果是就执行 afterSingletonsInstantiated()方法;

getBean过程: getBean(beanName);ioc.getBean;

  1. AbstractBeanFactory.doGetBean();
  2. 先获取缓存中保存的单实例bean,如果能获取到,说明这Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)从getSingleton方法中singletonObjects=new ConcurrentHashMap<String,Object>属性中获取到
  3. 缓存中获取不到,开始Bean的创建对象流程:
    • 标记当前Bean已经被创建,markBeanAsCreated(beanName);防止多线程bean重复创建
    • 获取Bean的定义信息:final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    • 获取当前Bean依赖的其它Bean;如果有,按照getBean()把依赖的Bean先创建出来
    • 启动单实例Bean的创建流程:

单实例Bean的创建流程:

  1. createBean(beanName,mbd,args);
    • Object bean = resolveBeforeInstantiation(beanName, mbdToUse);先让BeanPostProcessor【InstantiationAwareBeanPostProcessor】先拦截返回代理对象。先触发所有InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法,如果有返回值调用postProcessAfterInstantiation()方法
    • 如果没有返回bean,调用doCreateBean();Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      • 利用工厂方法或者对象的构造器等创建bean实例:createBeanInstance(beanName, mbd, args);

      • applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

      • 为bean的属性赋值:populateBean(beanName, mbd, instanceWrapper); 赋值之前:

        • 拿到InstantiationAwareBeanPostProcessor类型的后置处理器,执行postProcessAfterInstantiation();
        • 拿到InstantiationAwareBeanPostProcessor类型的后置处理器,执行postProcessProperties();

        赋值:

        • 应用Bean属性的值:为属性利用setter方法等进行赋值applyPropertyValues(beanName, mbd, bw, pvs);
      • bean初始化:initializeBean(beanName, exposedObject, mbd);(生命周期中介绍)

      • 注册bean的销毁方法:registerDisposableBeanIfNecessary(beanName, bean, mbd);

    • Bean的实例创建完成,将bean添加到缓存中:addSingleton(beanName, singletonObject);

ioc容器就是这些Map;很多Map里面保存了单实例bean,环境信息等...

9. finishRefresh();完成BeanFactory初始化创建工作;IOC容器就创建完成

  1. clearResourceCaches();清理一些资源缓存
  2. initLifecycleProcessor();初始化声明周期有关的后置处理器,允许我们写一个LifecycleProcessor的实现类,可以在BeanFactory进行到特定生命周期时进行调用 ​ 默认从容器中找是否有LifeCycleProcessor的组件,如果没有,默认会创建一个 new DefaultLifecycleProcessor();然后加入到容器中
  3. getLifecycleProcessor().onRefresh();拿到所有前面定义的生命周期处理器回调onRefresh()方法
  4. publishEvent(new ContextRefreshedEvent(this));发布容器刷新完成事件
  5. LiveBeansView.registerApplicationContext(this);

九. Spring容器创建总结

  1. Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息
    • xml注册bean < bean id="" class = "">
    • 使用注解;@Service、@Bean、@Component、...
  2. Spring容器会在合适的时机创建这些Bean
    • 用到这个bean的时候,利用getBean方法创建bean,创建好以后保存在容器中
    • 统一创建剩下所有bean的时候,即finishBeanFactoryInitialize();
  3. 后置处理器 每一个bean创建完成,都会使用各种后置处理器进行处理,来增强bean 的功能,如: + AutowiredAnnotationBeanPostProcessor会处理自动注入功能 + AnnotationAwareAspectJAutoProxyCreator来做AOP功能
  4. 事件驱动模型:
    • ApplicationListener:事件监听
    • ApplicationEventMulticaster:事件派发