文章目录
注意:这里只介绍脉络,各种的后置处理器以及循环依赖的问题后面会在各章节中详细介绍**
描述SpringIoc简单的一个加载流程
一个类通过注解的方式读取成统一的BeanDefinition
- 通过AnnotationConfigApplicationContext这个实现子类,具体会经过以下几个步骤
- BeanDefinition的实现子类AbstractBeanDefinition封装了一些基本属性
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
BeanDefinitionRead负责读取配置类
BeanDefinitionScanner扫描加了注解的类
BeanDefinitionRegistry负责将BeanDefinitionScanner扫描到的BeanDefinition注册进BeanDefinitionMap中
Spring扩展点:BeanFactoryPostProcessor
- 可以对上一步的BeanDefinition进行修改
- 是在ApplicationContext中完成的
Spring扩展点:BeanDefinitionRegistryPostProcessor
- 用来注册BeanDefinition
- 是在ApplicationContext中完成的
getBean()
Spring扩展点:BeanPostProcessor
- 创建Bean的过程中会调用一堆的BeanPostProcessor,具体的调用流程后面会详细介绍
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;
}
}
通过反射实例化
- 实例化后我们的Bean还是一个空壳,例如@AutoWired属性和@Value属性仍然是空的,只有那些有参构造传入的属性已经被填充过了
- 两种方法实例化
- 经过反射例如@Component注解,由Spring控制
- 工厂方法例如@Bean里面可以自己new一个对象返回,或者为某个对象设置动态代理;工厂方法更加灵活
填充属性
- 填充@Autowired和@value的属性
- 这里可能会有循环依赖,在这里会解决循环依赖
初始化
- 例如我们可以配置initMethod的方法在这个方法里面调用还有很多的后置处理器都会在这个方法里面
- 在这里面还有很多声明周期的回调方法(一堆Aware):EnvironmentAware,ApplicationContextAware
- 调用BeanPostProcessor#postProcessBeforeInitialization()方法
- 调用ApplicationContextAwareProcessor中的Aware方法
- @Postconstruct注解的方法也在这里调用
- 调用initMethod方法
- Spring为bean提供了两种初始化的方式,实现InitializingBean接口(也就是要实现该接口中的afterPropertiesSet方法),或者在配置文件或@Bean注解中通过init-method来指定,两种方式可以同时使用。
- 实现InitializingBean接口是直接调用afterPropertiesSet()方法,与通过反射调用init-method指定的方法相比,效率相对来说要高点。但是init-method方式消除了对Spring的依赖。
- 如果调用afterPropertiesSet方法时出错,那么就不会调用init-method指定的方法了
- 小结:
- 也就是说Spring为bean提供了两种初始化的方式,第一种方式是实现InitializingBean接口(也就是要实现该接口中的afterPropertiesSet方法),第二种方式是在配置文件或@Bean注解中通过init-method来指定,这两种方式可以同时使用,同时使用先调用afterPropertiesSet方法,后执行init-method指定的方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
......
......
......
}
else {
//调用实现了InitializingBean接口的afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
//从BeanDefinition中获取InitMethodName方法
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//调用该方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
- 调用BeanPostProcessor#postProcessAfterInitialization()方法
- Aop的构建就是在AbstractAutoProxyCreator#postProcessAfterInitialization()中
放到一级缓存里面
- singletonObjects:key是BeanName,value是经过上面步骤创建好的完整的Bean
Bean的生命周期
-
bean的实例化:调用bean的构造方法,我们可以在bean的无参构造方法中执行相应的逻辑。
-
填充属性:InstantiationAwareBeanPostProcessor的实现类
- AutowiredAnnotationBeanPostProcessor:用来解析AutoWired和value
-
bean的初始化:在初始化时,可以通过BeanPostProcessor的postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法进行拦截,执行自定义的逻辑;通过@PostConstruct注解、InitializingBean和init-method来指定bean初始化前后执行的方法,在该方法中咱们可以执行自定义的逻辑
-
bean的销毁:可以通过@PreDestroy注解、DisposableBean和destroy-method来指定bean在销毁前执行的方法,在该方法中咱们可以执行自定义的逻辑
流程图见上面
BeanFactory
- Spring顶层核心接口,使用简单工厂模式生产Bean
简单工厂模式
- Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
- 由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
实现原理
bean容器的启动阶段
- 读取bean的配置,将bean元素分别转换成一个BeanDefinition对象。然后通过BeanDefinitionRegistry(bean定义注册器)将这些bean注册到beanFactory中,保存在它的一个ConcurrentHashMap中。
- 将BeanDefinition注册到了beanFactory之后,在这里Spring为我们提供了一个扩展的接口,允许我们通过实现接口BeanFactoryPostProcessor 在此处来插入我们定义的代码。典型的例子就是:PropertyPlaceholderConfigurer,我们一般在配置数据库的dataSource时使用到的占位符的值,就是它注入进去的。
容器中bean的实例化阶段
- 实例化阶段主要是通过反射或者CGLIB对bean进行实例化,在这个阶段Spring又给我们暴露了很多的扩展点:
各种的Aware接口,比如 BeanFactoryAware,对于实现了这些Aware接口的bean,在实例化bean时Spring会帮我们注入对应的BeanFactory的实例。 - BeanPostProcessor接口,实现了BeanPostProcessor接口的bean,在实例化bean时Spring会帮我们调用接口中的方法。
- InitializingBean接口,实现了InitializingBean接口的bean,在实例化bean时Spring会帮我们调用接 口中的方法。
- DisposableBean接口,实现了BeanPostProcessor接口的bean,在该bean死亡时Spring会帮我们调用接口中的方法。
设计意义
- 松耦合。可以将原来硬编码的依赖,通过Spring这个beanFactory这个工长来注入依赖,也就是说原来只有依赖方和被依赖方,现在我们引入了第三方——spring这个beanFactory,由它来解决bean之间的依赖问题,达到了松耦合的效果.
- bean的额外处理。通过Spring接口的暴露,在实例化bean的阶段我们可以进行一些额外的处理,这些额外的处理只需要让bean实现对应的接口即可,那么spring就会在bean的生命周期调用我们实现的接口来处理该bean
BeanDefinition
- Spring顶层的核心接口,封装了生产Bean的一切属性
BeanFactory和ApplicationContext的区别
- ApplicationContext包括BeanFactory的所有功能,和Beanfactory相比更值得推荐,除了一些特定的场景, 例如在资源受限的设备上运行的内嵌的应用。
- 在ApglicationContext (例如 GenericAplicationContext实现)中,按照约定(即通过bean名称或bean类型 -特别是后处理器)检测到几种bean,而普通的 DefaultListableBeanF actory对任何特殊bean都是不可知的。
- 对于许多扩展容器功能,例如注解处理和AOP代理,BeanPostProcessor扩展点是必不可少的。如果仅使用普通的DefaultlistableBeanFactory ,则默认情况下不会检测到并激活此类后置处理器。这种情况可能令人困感,因为您的bean配置实际上没有任何问题。相反,在这种情况下,容器需要至少得多-些额外的处理。
ApplicationContext的结构图
- 从下面可以看到ApplicationContext实现了BeanFactory接口;有生产Bean的能力,会调用BeanFactory生产Bean
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eHLtjfaD-1658569817302)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1658539931851.png)]
注入Spring底层的组件
Spring提供了以下Aware
- BeanNameAware :Bean在BeanFactory中的名称
- BeanClassLoaderAware :Bean的ClassLoader
- BeanFactoryAware :Bean所在的BeanFactory
- EnvironmentAware :Bean运行时的依赖Enviroment
- EmbeddedValueResolverAware :Spring EL解析,解析如#{xxx}表达式。
- ResourceLoaderAware :加载Bean的ResourceLoader
- ApplicationEventPublisherAware :应用事件发布者
- MessageSourceAware :国际化的
- ApplicationContextAware : 应用上下文容ServletContextAware :Servlet上下文
第一部分Aware的调用
- Aware的使用场景:注入Spring底层的组件
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
......
......
......
......
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充属性
populateBean(beanName, mbd, instanceWrapper);
//初始化,在这里会调用一部分Aware方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
......
......
......
......
return exposedObject;
}
AbstractAutowireCapableBeanFactory#initializeBean()
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 在这里调用一部分Aware方法
invokeAwareMethods(beanName, bean);
}
......
......
......
......
}
AbstractAutowireCapableBeanFactory#invokeAwareMethods
- 自定义类实现这个接口,将这个值赋值到某个属性上面,在方法里面就可以使用这个方法
- 这些Aware并没有实现上面后置处理器,只是判断进来的bean是不是这些接口的实现类,如果是调用,将Bean转为对应类型,调用对应的方法进行注入
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
//调用BeanNameAware
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
//调用BeanClassLoaderAware
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
//调用BeanFactoryAware
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
第二部分Aware接口的调用
- 着重关注ApplicationContextAwareProcessor这个类
ApplicationContextAwareProcessor
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SIxtg8D6-1658569817305)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220511120833137.png)]
class ApplicationContextAwareProcessor implements BeanPostProcessor {
@Override
//调用postProcessBeforeInitialization方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//判断Bean有没有实现下面这些接口,没有实现直接返回,实现了调用invokeAwareInterfaces该方法
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
......
......
......
......
else {
//调用真正的Aware
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
//调用EnvironmentAware
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
//调用EmbeddedValueResolverAware
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
//调用ResourceLoaderAware
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
//调用ApplicationEventPublisherAware
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
//调用MessageSourceAware
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
///调用ApplicationContextAware
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//ApplicationContextAwareProcessor会在这里调用,调用上面的那些方法
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
使用案例
实现EmbeddedValueResolverAware接口
package com.meimeixia.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.util.StringValueResolver;
/**
* 以Red类为例来讲解ApplicationContextAware接口、BeanNameAware接口以及EmbeddedValueResolverAware接口
*
*/
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("传入的IOC:" + applicationContext);
this.applicationContext = applicationContext;
}
/**
* 参数name:IOC容器创建当前对象时,为这个对象起的名字
*/
@Override
public void setBeanName(String name) {
System.out.println("当前bean的名字:" + name);
}
/**
* 参数resolver:IOC容器启动时会自动地将这个String值的解析器传递过来给我们
*/
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String resolveStringValue = resolver.resolveStringValue("你好,${os.name},我的年龄是#{20*18}");
System.out.println("解析的字符串:" + resolveStringValue);
}
}