Spring中Bean的生命周期
摘要:
本文主要学习内容
1、在学习Spring源码之前我们可以先搞懂几个概念,这也是很重要的一些概念(为源码阅读做准备)。
2、Spring的Bean的生命周期。
3、Spring是如何利用三级缓存来处理循环依赖的。
1 什么时Spring?
Spring就是一款帮助我们管理对象的工具,它帮助我们创建Bean对象,并且管理对象与对象之间的依赖关系等。
2 Bean和对象的区别?
所有的Bean一定是一个对象,但是一个对象不一定是一个Bean;
说白了,经过我们Spring完整生命周期的对象就是Spring的Bean。
3 最基本的Bean的生命周期会有几步?
首先扫描所有注解获取到class字节码
然后去根据class去new instance() 就是实例化
然后填充属性
然后进行Aware(可以去获取我们的BeanName,BeanFactory等)
然后去初始化
然后去执行AOP
最后放到单例池
这就是简单的Spring的生命周期
4 什么是BeanDefination?
BeanDefination是对Bean对象的描述;
在创建Bean时候Spring就会根据这个BeanDefination去创建我们的Bean;
其中重要属性有:
1 beanClass :
表示Bean的类型,Spring会根据他来实例化得到对象
2 scope:
表示作用域,singleton表示单例,prototype表示原型Bean
3 isLazy:
表示一个Bean需不需要懒加载,原型Bean的@Lazy注解不起作用,
需要懒加载的单例Bean会在第一次getBean的时候生成Bean,
非懒加载的单例Bean会在Spring启动的时候直接创建好放到单例池;
4 dependsOn:
表示Bean所依赖的其他Bean对象,在创建该Bean之前,它 所依赖的其他Bean对象需要事先创建好;
5 primary:
表示一个Bean是主Bean在Spring中一个类型的Bean可以有多个比Service接口可以有多个实现类,
在Spring进行依赖注入的时候,如果根据类型寻找到多个Bean对象如果某一个Bena上加了@Primary注解,就会注入该主Bean
6 initMethodName:
表示一个Bean的初始化方法,一个Bean的生命周期有一个过程叫做初始化,Spring在初始化的时候会去调用Bena的初始化方法
初始化逻辑可以由程序员自己定义来控制Bena的初始化。
5 什么是BeanFactoryPostProcessor?
就是Bean工厂的后置处理器,
这个后置处理器可以操作beanFactory,
通过beanFactory拿到BeanDefination
这样也就是说我们可以在Spring实例化Bean之前随心所欲的操作Bean对象的创建过程;
那么什么时候才能知道BeanFactory创建完毕了呢?
其实当我们的BeanDefination创建完毕之后会放到的BeanFactory的一个容器中BeanDefinationMap,所以当我们的?BeanDefinationMap填充完之后我们的BeanFactory也就创建完毕了;
其实BeanFactoryPostProcessor还***可以与Mybatis整合***,我们可以在BeanFactoryPostProcessor接口的方法 postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)中利用beanFactory.registerSingleton(“userMapper”,userMapper);
自己实现BeanFactoryPostProcesor操作BeanDefinition的逻辑代码
/**
* 自定义BeanFactory后置处理器(Bean工厂后置处理器)
* 也就是在Bean工厂创建完毕之后,可以在这里完成对BeanFactory的处理,也就是当BeanDefinatioonMao创建结束之后就会执行该方法
*
* @ProjectName: spring
* @ClassName: MyTestBeanFactoryPostProcessor
* @Author: MrKay
* @Date: 2021/6/10
*/
@Component
public class MyTestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* BeanFactory创建完毕之后会去执行该方法来完成对BeanFactory的后置操作
*
* @param beanFactory
* @MethodName: postProcessBeanFactory
* @return: void
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition bd = (GenericBeanDefinition) beanFactory.getBeanDefinition("testBeanService");
// BeanDefinition bd = beanFactory.getBeanDefinition("testBeanService");
//获取要创建的Bean的Scope属性
System.out.println(bd.getScope());//singleton
//设置要创建Bean的Scope属性
// bd.setScope("singleton");
//获取要创建Bean的className
String className = bd.getBeanClassName();
System.out.println(className);//show.mrkay.service.TestBeanService
bd.setBeanClass(Person.class);
//我们在Service中注入Mapper的时候其实是Mybatis使用jdk动态代理生成的一个代理对象,
//那么Spring是如何将Mybatis生成的Mapper代理对象注入到我们的xxxMapper中的呢?
//一种方法就是使用这种,我们直接将Mybatis生成的代理对象放进去即可,另一种就是使用FactoryBean参考MyTestFactoryBean中实现方式
//模拟Mybatis使用JDK动态代理生成的Mapper代理对象
/*Object target = Proxy.newProxyInstance(UserMapperImpl.class.getClassLoader(), UserMapperImpl.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});
//将我们的Mybatis生成的代理对象注册成单例对象被Spring管理:这样也就完成了与Mybatis整合的灵魂
beanFactory.registerSingleton("userMapper",target);*/
}
}
6 什么是BeanPostProcessor?
就是Bean的后置处理器;
它是Spring提供的一种机制,利用该机制可以对Bean进行定制化加工,
在Spring底层源码中也广泛利用了该机制
比如:
可以操作Bean的实例化过程和初始化过程;
在实例化之前可以操作实例化之后也可以操作,
在初始化之前也可以操作,在初始化之后也能够操作;
BeanPostProcessor是一个接口,其中方法有:
1 postProcessBeforeInitialization() : 初始化前方法,表示可以利用这个方法来对Bean在初始化前进行自定义加工;
2 postProcessAfterInitialization(): 初始化后方法,表示可以利用这个方法来对Bean初始化后进行自定义加工;
InstatiationAwareBeanPostProcessor
是BeanPostPocessor的子接口,其内部有三个方法:
postProcessorBeforeInstantiation() : 实例化前方法,可以在实例化前对Bean进行加工;
postProcessorAfterInstantiation() :实例化后方法,可以在实例化后对Bean进行加工;
postProcessProperties(): 属性注入后方法,可以在属性注入后对Bean进行操作;
7 FactoryBean和Applicationcontext和BeanFactory区别?
7.1 什么是FactoryBean?
FactoryBean是Spring提供的一种灵活的创建Bean的方式;
我们可以通过FactoryBean提供的getObject()方法,来返回一个对象,这个对象就是最终的Bean对象
FactoryBean是一个接口:
此接口里面有三个方法,getObject()方法返回的是Bean对象
getObjectType()返回的是Bean对象的类型;
isSingleton()返回的是一个bollean类型,表示是否是一个单例对象,此方法default修饰了,所有我们默认可以不需要覆盖此方法.
FactoryBean被广泛的用于第三方框架与Spring的整合过程中,例如我们的Mybatis就是利用此FactoryBean来完成与Spring的整合的(具体参考SpringMybatis的整合原理实现)
7.2 什么是ApplictionCntext?
ApplicationContext是比BeanFactory更加强大的Spring容器;
它可以创建Bean,获取Bean,还支持国际化,事件广播,获取资源等BeanFactory所不具备的功能;
ApplicationContext继承的接口有
EnvironmentCapable :
继承此接口可以获取环境变量,ApplicationContext就可以操作系统环境变量和JVM环境变量.
ListableBeanFactory :
继承此接口就表示可以获取到beanNames,判断某一个beanName是否存在beanDefinition对象,统计BeanDefinition个数等.
HierarchicalBeanFactory:
继承此接口就表示可以获取父BeanFactory,判断某一个name是否存在bean对象的功能 .
MessageSource:
继承此接口就表明ApplicationContext接口具有了国际化等功能,比如可以利用MessageSource来获取某个国际化资源(如不同国 家的语言对应的字符)
ApplicationEventPublisher
继承子接口,就表明ApplicationContext拥有了事件发布功能,这也是ApplicationContext相比于BeanFactory常用的功能.
ResourcePatternResolver
继承此接口就拥有了可以加载并获取资源的功能,这个资源可以是文件图片URL等.
7.3 什么是BeanFactory?
BeanFactory是一种Spring容器,字面意思就是Bean工厂
它可以用来创建Bean获取Bean,BeanFactory是Spring非常重要的组件。
BeanDefinition就像是BeanFactory的原材来,我们的BeanFactory拿到BeanDefinition来生成我们的Bean对象。
BeanFactory有这样集合核心子接口和实现类:
1 ListableBeanFactory
2 ConfigurableBeanFactory
3 AutowiredCapableBeanFactory
4 AbstractBeanFactory
5 DefaultListableBeanFactory
其中最重要的是DefaultListableBeanFactory:
它可以支持单例Bean,支持Bean的别名,支持父子BeanFactory,支持Bean类型转换,支持Bean的后置处理,支持FactoryBean,支持自动装配等。
7.4 FactoryBean和BeanFactory区别?
FactoryBean本身就是一个对象,同时它也相当于一个小型?Bean工厂,可以生成出另外一个Bean;
BeanFactory是个大的Bean工厂,它可以生产出各式各样的Bean对象,包括FactoryBean;
8 @Import @Component @Bean的区别?
上面三种注解其实都可以声明一个Bean
其实除了上面三种注解之外FactoryBean也可以创建Bean对象,同样我们也可以使用BeanFactoryPostProcessor来操作beanFactory它可以将一个普通对象注册为一个单例对象beanFactory.registerSingleton(“bean”,new Person());
@Import(Class[])
此注解使用在类或者接口上,并且是运行时有效,它可以导入一个Bean,
此注解一般会用于导入***ImportBeanDefinitionRegistrar***的实现类具体卡伊参考(Spring与Mybatis的整合原理)
@Compoent
Spring启动默认会去扫描的注解,通过扫描此注解生成class对象,最后走Spring的生命周期;
@Bean注解
使用在方法上,也可以实现注入一个Bean,但是一般当我们用到第三方框架的时候会去使用该注解.
9 Spring的生命周期源码解读
上面是Spring生命周期中使用到的一些知识点,那么下面开始看一下Spring生命周期的源码,从源码角度了解一下Spring的生命周期到底是怎样的
9.1 Bean的生命周期源码流程(不考虑AOP和循环依赖)
这里使用AnnotationConfigApplicationContext来完成从Spring中获取Bean来看一下Spring的是如何走完一个Bean的生命周期的.
首先Spring启动先进入到***AnnotationConfigApplicationContext***的构造方法中,当然如果我们使用的xml配置的方式会进入到***ClassPathXmlApplicationContext***的构造函数中(两者唯一区别是一个是基于xml配置的,一个是基于注解配置的,因为我们之前查看依赖注入的源码的时候就是使用的基于注解的方式,所以这里还继续使用注解的方式)
public class BeanLifeClient {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(AppConfig.class);
TestBeanService testBeanService = (TestBeanService) app.getBean("testBeanService");
System.out.println(testBeanService);
//获取AService验证循环依赖的时候使用
// AService aService = app.getBean("AService",AService.class);
// System.out.println("get Service .....lk......"+aService);
//获取FactoryBean中生成的代理对象
//可以看到这里返回的是Person对象并不是我们的MyTestFactoryBean对象
// Object factoryBean = app.getBean("myTestFactoryBean");
// System.out.println(factoryBean);//show.mrkay.pojo.Person@5e403b4a
}
}
进入到构造函数内部
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
//此方法中会继续宁Bean的生命周期
refresh();
}
进入到refresh()方法: 对于了解Bean的生命周期我们只需关注***finishBeanFactoryInitialization()***方法
此方法内部是在***实例化非懒加载的单例Bean***,可以看出就是在实例化我们最基本的单例Bean
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//准备此上下文以进行刷新
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//告诉子类刷新内部 bean 工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//准备在这种情况下使用的bean工厂。
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//允许在上下文子类中对 bean 工厂进行后处理。
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 注册Bean工厂后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册拦截Bean创建的Bean后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//初始化此上下文的消息源
initMessageSource();
// Initialize event multicaster for this context.
//为此上下文初始化事件多播器。
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//初始化特定上下文子类中的其他特殊 bean。
onRefresh();
// Check for listener beans and register them.
//检查侦听器bean并注册它们。
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//实例化非懒加载的单例Bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//发布事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
进入到***finishBeanFactoryInitialization(beanFactory)*方法内部,了解Spring的生命周期我们现在没必要对每一个方法都清楚,我们只需要关注其内部的beanFactory.preInstantiateSingletons();***方法即可
/**
* 实例化非懒加载的单例Bean
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
//为此上下文初始化转换服务。
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
//如果之前没有任何bean后处理器
// (例如,PropertyPlaceholderConfigurer Bean)进行任何注册,
// 请注册一个默认的嵌入式值解析器:此时,主要用于注释属性值的解析。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
//真正执行实例化非懒加载的单例Bean
beanFactory.preInstantiateSingletons();
}
接着进入到***beanFactory.preInstantiateSingletons();***方法内部,这个方法,这时候会进入到***ConfigurableListableBeanFactory***接口中的下面这个方法中
void preInstantiateSingletons() throws BeansException;
我们继续往里走,这个接口有一个默认的实现类***DefaultListableBeanFactory***我们上面介绍BeanFactory的时候有对这个实现类进行介绍.
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
//beanDefinitionNames这个容器它是BeanFactory的一部分,这里存放了所有Spring扫描到的Bean的name
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//这里就是根据BeanName去BeanDefinition中寻找Bean的定义然后逐个去进行实例化
for (String beanName : beanNames) {
//合并BeanDefinnation
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//判断该BeanDefination是不是抽象,单例,懒加载,都不是的话进入此分支
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断是不是一个FactoryBean,是的话进入此分支
if (isFactoryBean(beanName)) {
//获取Bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
} else {
//不是FactoryBean进入这里获取Bean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
接着进入到***getBean(beanName);***方法中,这个方法是在***AbstractBeanFactory***中的
@Override
public Object getBean(String name) throws BeansException {
//真实获取Bean
return doGetBean(name, null, null, false);
}
接着进入到***doGetBean(name, null, null, false);***方法,这个方法也是在***AbstractBeanFactory***中的,
下面关键方法在注解中有了详细介绍,这里只对非常重要的步骤进行再次介绍.
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
//对BeanName进行转换
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//缓存中是否已经存在(单例池(一级缓存)中是否存在,二级缓存中是否存在,三级缓存中是否存在)
Object sharedInstance = getSingleton(beanName);
//单例池里面有直接走此分支
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
//单例池里面没有进入此分支
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//返回创建的原型Bean是否正在创建中,如果是大概率处于循环依赖中
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//获取父类的bean工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
//当前bean工厂中不存在该BeanName的BeanDefination,那么就到父类的Bean工厂中去找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//BeanDefination合并
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//检查是否加了@DependOn注解:此注解表示当前要创建的Bean依赖了其他的Bean
//如果依赖了其他的Bean会先去创建好依赖的Bean才会去创建当前Bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
//实例化: 开始创建实例Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//开始创建实例Bean
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
} catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
首先我们可以看到在doCreateBean方法中
1 Spring首先会调用***getSingleton(beanName);***方法先从单例池中寻找(其实里面分别是从三级缓存中寻找的后面会详细介绍此方法在出现循环依赖和AOP的情况下如何使用的这也是Spring的精妙之处)。这里是我们是刚进来我们就先默认为单例池里面没有即可。
接着我们进入***createBean(beanName, mbd, args);***方法,这个方法的具体实现是在***AbstractAutowireCapableBeanFactory***中完成的,它是***AbstractBeanFactory***的一个子类。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 1:实例化前,
// 调用Bean的后置处理器,让其有机会返回一个代理的Bean对象,
//说白了就是实例化前我们可以自己控制我们的Bean对象,比如我们可以自己创建一个对象进行返回都可以
//具体怎么做的可以看一下里面方法
//官方对该方法的解释:应用实例化前的后处理器,解决指定 bean 是否有实例化前的快捷方式
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//创建Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
//直接返回最终会将创建的Bean放到单例池里面其,到此实例化单例Bean的过程结束
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
可以看到在实例化对象之前是有一个操作的,这就是我们在之前讲到的BeanPostProcessor后置处理器中***postProcessorBeforeInstantiation()***方法来完成实例化之前的一些操作,
我们先进到这个方法看一下***Object bean = resolveBeforeInstantiation(beanName, mbdToUse);***
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//实例化前
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
//applyBeanPostProcessorsBeforeInstantiation()方法
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//InstantiationAwareBeanPostProcessor 这个是一个实例化Aware后置处理器
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//调用实例化前的后置处理器方法
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
上面方法可以看到:
真正进行实例化前Spring会在For循环执行***InstantiationAwareBeanPostProcessor***的实例化前方法***postProcessBeforeInstantiation(beanClass, beanName)***所以,并且可以看到如果返回的Bean不是null会直接进行返回该BeanBean的生命周期也就结束了为了证明这一点,下面我们自己定义一个实习实现类验证一下.
//自定义InstantiationAwareBeanPostProcessor实现类,并重写postProcessBeforeInstantiation(beanClass, beanName)方法
@Component
public class MyTestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* 在 实例化前 会进入到我们自定义的这个方法我们可以对Bean进行操作,想怎么操作就怎么操作
*
* @param beanClass
* @param beanName
* @MethodName: postProcessBeforeInstantiation
* @return: java.lang.Object
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return new Person();
}
}
调试截图:
我们希望在获取TestBeanService的时候返回的结果是Person。
下面截图也可以看到:我们的BeanName是testBeanService但是经过***InstantiationAwareBeanPostProcessor***处理之后返回的Bean是一个Person对象,这也证明了我们上面分析的结果.
接着往下走,我们进入到***doCreateBean(beanName, mbdToUse, args)***方法中查看真正开始创建Bean对象的过程.(中间关于循环依赖的注释先不用在意,后面会详细讲解)
下面注释步骤也很详细,可以看出Spring先进行了实例化,而实例化内部具体的逻辑就是通过BeanDefinition推断构造方法,然后通过反射创建一个对象.
接着看实例化之后,就开始调用***populateBean(beanName, mbd, instanceWrapper);***方法进行填充属性;
属性填充完成之后就会进行初始化.
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 2:实例化:
if (instanceWrapper == null) {
//创建Bean实例,推断构造方法,返回的BeanWrapper 结果就是一个包裹对象
//包裹对象里面包含了我们创建的原始对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//原始对象,还没进行初始化,属性还没有值
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//如果当前创建的是单例Bean,并且允许循环依赖,并且还在创建过程中,那么则提早暴漏
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
//可以看到如果出现了循环依赖这里会将一个Lambda表达式放到一个SingletonFactorysMap中,这就是我们的第三级缓存
//可以进入到方法中看一下
//为什么是一个Lambada表达式呢?
// 我们知道在放入的时候不会去执行,只有到用的时候Spring才会去执行它,这里存放到三级缓存中的lambda
//可能是需要进行AOP的,也可能不需要进行AOP
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//这里就是我们处理过后的原始对象,还没有填充属性
Object exposedObject = bean;
try {
//3: 实例化后:
// 开始填充属性(可以知道填充属性的过程发生在实例化后其实只要有点常识都能知道,还没有实例化怎么进行属性填充呢)
//可以想到其实我们的依赖注入其实也是Bean的生命周期的一部分,开始对注入点注入属性就是在这里开始的(当然)
//我们可以进去看一下方法内容
populateBean(beanName, mbd, instanceWrapper);
//4:初始化,实例化后开始进行初始化,
// (这里执行完之后就可以看到我们实现的InitializingBean接口方法中对username的赋值操作就会执行)
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//提前进行了AOP就会进入到这个分支
if (earlySingletonExposure) {
//从三级缓存中寻找
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//如果提前暴露的对象和经过了完整生命周期的Bean对象exposedObject和原始对象bean相等则进入分支,把代理对象赋值给exposedObject
//然后将exposedObject返回放到单例池中
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
看一下Spring是如何进行属性填充的,我们进入到***populateBean(beanName, mbd, instanceWrapper);***方法内部看一下
可以看到在内部Spring执行了***InstantiationAwareBeanPostProcessor***后置处理器的***postProcessAfterInstantiation()***方法和***postProcessProperties()***方法,其中第二个方法就是我们之前在依赖注入源码阅读里面讲到的注入属性的方法.可将依赖注入确实是发生在实例化之后开始填充属性的时候,并调用的是***InstantiationAwarePostProcessor***后置处理器来完成的.
同样我,们可以重写***InstantiationAwarePostProcessor***这两个方法,看一下.
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
//可以看到实例化后调用了InstantiationAwareBeanPostProcessor实例化后置处理器的postProcessAfterInstantiation方法--lk
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
//根据Name去寻找Bean
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
//根据Type去寻找Bean
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//执行注入属性的逻辑
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
重写
@Component
public class MyTestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* 在 实例化前 会进入到我们自定义的这个方法我们可以对Bean进行操作,想怎么操作就怎么操作
*
* @param beanClass
* @param beanName
* @MethodName: postProcessBeforeInstantiation
* @return: java.lang.Object
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println(beanName + "=" + beanClass);
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
/**
* 在 实例化后 会进入到我们自定义的这个方法我们可以对Bean进行操作,想怎么操作就怎么操作
*
*
* @MethodName: postProcessBeforeInstantiation
* @return: java.lang.Object
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "=" + bean);
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
/**
* 可以看到这个就是我们在Spring的依赖注入中,注入属性中使用的方法,
* 这里也可见其实Spring就是在Bean实例化之后开始执行我们依赖注入的那部分逻辑,完成属性的注入和填充
*
* @param pvs
* @param bean
* @param beanName
* @MethodName: postProcessProperties
* @return: org.springframework.beans.PropertyValues
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println(pvs);
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}
调试截图如下:
接着往下走:
实例化之后,接下来就是初始化了,
我们进入初始化方法内部***initializeBean(beanName, exposedObject, mbd);***
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
//4.1: 执行Aware(在初始化前会去执行BeanNameAware接口下的方法可以参考TestBeanService)
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//4.2: 初始化前:
// 其实内部会调用BeanPostProcessor后置处理器的初始化前处理方法
//可以进入到此方法内部看一下
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//4.3: 初始化:
//其实内部会执行 InitializingBean 接口的afterPropertiesSet方法,
//此方法会在Spring将属性设置完毕之后进行操作
// (如: 我们的TestBeanService已经实现了该接口所以这个方法执行执行username是没有值的,这个方法执行之后username就会有值)
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()) {
//4.4: 初始化后:
//可以看到初始化后流程就结束了,直接return了我们的结果
//其实初始化后的方法其实就是判断我们的对象是不是配置AOP切面,如果配置了就会返回一个代理对象
//可以知道AOP其实是在初始化后执行的
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
//返回我们的包裹类
return wrappedBean;
}
上面代码和实例化的步骤很相似,在初始化的时候也会经过执行Aware方法,初始化前,初始化,以及初始化后;
执行Aware方法我们进入到内部看一下***invokeAwareMethods(beanName, bean);***
下面步骤也很详细了,这个方法就是当我们在自定义的Bean中想要知道我们的BeanName或者Bean的加载器,以及创建Bean的工厂就可以实现***BeanNameAware***和***BeanClassLoaderAware***以及***BeanFactoryAware***接口
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
//是不是实现了BeanNameAware接口
//此接口可以获取Bean的名字
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
//BeanClassLoaderAware此接口可以获取当前Bean初始化的Bean时哪一个ClassLoader加载的
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
//BeanFactoryAware 接口可以获取当前初始化的Bean是哪一个Bean工厂创建的
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
下面我们让TestBeanService实现上面说的接口调试看一下(这里举例说明即可所以我只实现了两个接口)
先不要管***InitializingBean***接口,后面会介绍到
@Service
public class TestBeanService implements InitializingBean, BeanNameAware , BeanFactoryAware {
@Autowired
private User user;
@Autowired
private UserMapper userMapper;
@Autowired
private OrderMapper orderMapper;
private String username;
/**
* 实现 InitializingBean 接口之后 需要覆盖此方法
* 此方法会在Spring 初始化Bean的时候调用,可以看出他是在属性设置完毕之后
* (既然都执行了初始化当然属性也都设置完毕了.因为填充Spring的属性是在实例化之后完成的)
* 采取执行的这个方法
*
* 用于设置我们自己想要做的一些操作比如这里是在Spring帮我们把属性设置完成之后,
* 我们如果还需要给username赋值一个默认值就可以在此方法中完成
*
* @param
* @MethodName: afterPropertiesSet
* @return: void
*/
@Override
public void afterPropertiesSet() throws Exception {
this.username = "123";
}
/**
* 这个方法时实现了BeanNameAware接口之后重写的方法,此方法可以获取到当前Bean的name
* @MethodName: setBeanName
* @param name
* @return: void
*/
@Override
public void setBeanName(String name) {
System.out.println("BeanName==="+name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println(beanFactory);
}
}
调试截图(主要看控制台输出即可)
接着
我们进入到初始化前***applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);***方法内部看一下到底执行了什么逻辑
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
//existingBean就是当前初始化过程中的单例Bean
Object result = existingBean;
//遍历所有的BeanPostProcessor后置处理器,然后挨个去执行初始化前的方法
//其实这里我们的Bean就可以实现该接口重写该初始化前的方法,到了这里Spring就会去执行我们自己重写的初始化前方法,
// (比如我们可以在TestBeanService中实现BeanPoetProcessor接口然后重写该方法即可)
//但是一般这样做意义不太大,因为还没有初始化完成,所以意义并不大
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
为了验证上面逻辑我们可以自定义一个Bean的后置处理器,实现***BeanPostProcessor***并重写其内部初始化前犯法看一下
@Component
public class MyTestInitializationBeanPostProcessor implements BeanPostProcessor {
/**
* 初始化前执行的方法
* @MethodName: postProcessBeforeInitialization
* @param bean
* @param beanName
* @return: java.lang.Object
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
/**
* 初始化后执行的方法
* @MethodName: postProcessAfterInitialization
* @param bean
* @param beanName
* @return: java.lang.Object
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
测试截图
可以看到确实进入到了BeanPostProcessor的初始化前方法内部,不过Spring在初始化前几乎不会对Bean做什么改动,因为还没有进行初始化所以没必要做很多操作.但是后面我们说的初始化后方法就很麻烦了.
接着往下走:
初始化方法***invokeInitMethods(beanName, wrappedBean, mbd);***我们进入到内部源码看一下
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
//判断该Bean是不是实现了InitializingBean接口,如果实现了就执行自定义的afterPropertiesSet逻辑代码,用于设置我们自己的一些属性到Bean的生命周期中
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) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
//执行
((InitializingBean) bean).afterPropertiesSet();
}
}
//这个分支是执行我们在下xml中配置的自定义初始化方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
我们上面代码其实已经看到了***TestBeanService***已经实现了***InitializingBean***接口,所以我们只需要看一下初始化方法执行完毕之后我们的username会不会有值就行了
测试截图:(证明确实执行了)
接着往下走:
初始化后方法***applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);***可以发现这个方法执行完毕之后后面就直接返回了,说明Spring中Bean的生命周期也已经结束了.
来看一下初始化后方法内部的逻辑
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
//遍历所有实现了BeanPostProcessor的接口,然后执行初始化后的方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看到其实初始化后的方法内部还是在执行***BeanPostProcessor***的***postProcessAfterInitialization()***初始化后方法,我们在没有循环依赖的情况下使用的就是在初始化后处理AOP的.后面会在循环依赖的地方讲解Spring如何处理AOP和循环依赖的.
9.2 Spring生命周期(不考虑AOP和循环依赖)的流程梳理
上面通过对源码阅读大致可以看出来Spring基本的生命周期,也是最简单的生命周期.因为这种情况还没有考虑到AOP和循环依赖,如果考虑到AOP和循环依赖,Bean的生命周期就会受到这两种情况的影响;
下面梳理一下简单的Bean的生命周期.
1、首先Spring启动后会去扫描所有注解(这里以注解方式为例)生成对应的class文件,以及scope等其他属性,将其用BeanDefinition封装后,放入到BeanFactory的beanDeginitionMap中;这样创建Bean的"原料"就有了
2、然后Bean工厂根据这些“原料”执行实例化前,实例化,实例化后,初始化前,初始化,初始化后的流程,最后把创造出来的Bean对象放到单例池中(这一这里是以单例Bean为例解说的生命周期,如果是原型BEan就不会放到单例池中)
3 其中在
实例化前会去调用InstatiationAwareBeanPostProcessor的实例化前方法对Bean进行加工
实例化会根据BeanDefinition推断构造函数,来创建Bean的原始对象(还没有填充属性)
实例化后会去调用InstatiationAwareBeanPostProcessor的实例化后方法对Bean对象进行加工,并在实例化后对Bean中的属性进行填充。
初始化后在没有AOP或者循环依赖的情况下就回去进行AOP的相关操作。
流程图如下:
10 Spring如何处理循环依赖?(不考虑AOP)
大概知道了Spring简单的生命周期,那么循环依赖是如何解决的呢?我们先来看一下在***不使用AOP***的情况下的解决思路?
如图:
上图可以看到在***没有使用AOP***的情况下,
我们我们只需要提前将A缓存起来即可,当出现循环依赖的时候直接从缓存中取出来,注入给B中的A属性,接着完成B的创建过程和生命周期.
回过头来继续执行A的创建生命周期,当需要注入B的时候,此时单例池中已经有了B,所以可以直接取出来注入到A中的B属性即可.
最后循环依赖就解决了.
思考一下:
如果出现了AOP会出现什么问题?该怎么解决?
11 循环依赖如果出现了AOP如何解决?
基于第10步中的思考,我们考虑一下如果出现AOP会出现什么问题?
11.1 分析AOP会在循环依赖中带来的问题
可以看着下面这张图分析一下:
我们知道缓存中存放的是***AService的原始对象***;
当Spring执行到注入属性的时候,发现AService中需要注入BService的时候,就会去执行BService的生命周期;
当BService执行过程中发现需要注入AService的属性,这个时候按照我们正常思路就会去缓存中拿出***Aservice的原始对象***完成属性的注入;
当BService生命周期执行结束,BService也就已经放到了单例池中;
这个时候AService继续完成属性注入操作,从单例池中扎到了BService并完成了属性注入;
接着继续走自己的生命周期,当走到初始化之后的时候发现Aservice配置了AOP,就会在初始化之后执行AOP;
我们知道AOP内部使用的是动态代理的方式,所以会基于Aservice生成一个代理对象;
最终Aservice生命周期走完,生成的***代理对象***放入单例池;
那么问题就出现了:
我们在BService的生命周期中注入的Aservice属性是***AService的原始对象***,但是我们在单例池中存放的是***AService的代理对象***,其实我们应该将***AService的代理对象***赋值给BService中的Aservice属性.这就是AOP给循环依赖带来的问题.
11.2 解决AOP给循环依赖带来的问题
问题既然出现了那么该怎么解决这个问题呢?
11.2.1 解决思路和方案
要解决这个问题我们应该先明确一点AOP是个什么玩意儿?他到底什么时候会去执行?
首先AOP我们都知道基于动态代理的,它就是一个切面,可以对目标方法进行增强,或者利用AOP进行日志的处理,还有就是AOP就像是Spring的一个插件一样,不是说你使用了Spring就会执行AOP,他的执行要看你用不用它,配置了AOP它就会去执行,没有配置就不会去执行.
清楚了AOP只要我们对目标对象方法配置了AOP它才会去执行这一点,我们下面理解起来就会很轻松.
解决思路:
既然我们Aservice需要执行AOP的逻辑,而Bservice需要注入的是Aservice的代理对象,
那么我们可不可以在BService去缓存中获取AService的时候直接把AService的AOP逻辑给做了?
这样BService生命周期结束之后,它的AService属性自然就是一个Aservice的代理对象,
回过头来接着执行AService的生命周期,当AService执行初始化后的时候在去判断是不是已经进行过了AOP,
如果已经进行了AOP就不再执行AOP逻辑即可.
注意我们上面说的缓存就是第三级缓存:singletonFactories 它是一个HahsMap,value的类型是ObjectFactory一个函数式接口,所以可以使用Lambda表达式.(后面源码可以看出)
答案当然是可以的,可能有人会问在从缓存中获取AService的时候Spring怎么知道它需不需要进行AOP呢?还有从缓存中获取出来的是一个对象怎么进行AOP逻辑呢?Spring判断出现了循环依赖的呢?
这几个个问题很容易理解:
第一点: 开始就说了AOP就像是Spring的一个插件,你给目标对象配置了AOP的话Spring就会知道.
第二点: 这一点其实很简单,你都已经拿到了原始对象,Spring还怕不知道怎么执行AOP逻辑吗?
第三点: 其实Spring在创建执行对象的生命周期的过程中会记录(使用的是一个Set集合记录的*)正在创建的对象,当在执行另一个对象的生命周期的过程中,发现需要注入上一个对象,这时候如果发现上一个对象在这个Set集合中证明这个对象也正在执行生命周期,这时候就证明出现了循环依赖.
解决思路流程图:
1、首先当AService将实例化的AService放到一个Set集合中,这个集合中存放的原始对象表达正在创建过程中;
2、然后将我们生成的AService的原始对象封装到一个函数式接口***ObjectFactory***中,存到***singletonFactories***第三级缓存中;
3、当AService注入BService属性的时候,会先从***单例池一级缓存***中寻找,因为这时候BService还没有实例化也就没有再创建中,所以这时候不会从三级缓存中找。所以最终找不到BServbice就会去执行BService的生命周期。
4、在执行BService的生命周期时,到需要注入AService的时候,同样也先从***一级缓存单例池***里面寻找,很早不到,这个时候AService已经在创建过程当中了,并且之前也已经实例化了,所以最终会在三级缓存中找到。
5、找到之后去执行ObjectFactory函数式接口的Lambda表达式,如果配置了AOP就会生成一个代理对象,注入到BService的AService属性,如果没有配置AOP就会返回一个原始对象注入到BService的AService属性。
6、接着BService继续完成它自己的生命周期,最终放入到单例池中。
7、BService的生命周期结束,回过头来继续执行AService中注入BService属性的流程,这时候,在***一级缓存单例池***中就能找到BService,最终将BService注入到AService的bService属性。
8、接着执行AService的生命周期,到了初始化后,这时候如果配置了AOP就会在***AbstractAutoProxyCreator***这个***Bean的后置处理器***中的*初始化后方法中去判断是不是已经提前进行了AOP,如果提前进行了AOP就不再执行AOP逻辑,如果没有就会去执行AOP逻辑返回代理对象。
9、最终将AService生命周期结束。
11.2.2 源码分析Spring解决循环依赖中出现AOP的情况
上面已经分析了,解决思路和方案,下面从源码角度分析一下:
首先看一下Spring是如何解决循环依赖中的AOP问题的
首先看下面一部分代码这部分代码是在Spring实例化对象之后做做的操作
其中***isSingletonCurrentlyInCreation(beanName)***是在判断当前Bean是不是正在创建过程当中
***addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));***方法就是我们的当前的原始对象放到三级缓存***singletonFactories***中,这也正好与我们上面图中的流程一致,以ObjectFactory这样一个函数式接口存放到三级缓存中
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
//...code...
//...
//如果当前创建的是单例Bean,并且允许循环依赖,并且还在创建过程中,那么则提早暴漏
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
//可以看到如果出现了循环依赖这里会将一个Lambda表达式放到一个SingletonFactorysMap中,这就是我们的第三级缓存
//可以进入到方法中看一下
//为什么是一个Lambada表达式呢?
// 我们知道在放入的时候不会去执行,只有到用的时候Spring才会去执行它,这里存放到三级缓存中的lambda
//可能是需要进行AOP的,也可能不需要进行AOP
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//...code...
//...
}
//isSingletonCurrentlyInCreation(beanName)
//返回指定的单例 bean 当前是否正在创建中(在整个工厂内)
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
//addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//将我们的Lambada表达式放到第三级缓存中
this.singletonFactories.put(beanName, singletonFactory);
//从二级缓存中移除
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
上面代码看到确实是把原始对象以lambda表达式的形式存放到的三级缓存中,但是话说回来但是这和解决循环依赖以及AOP有什么关系呢?
首先我们们知道Lambda表达式在存放的时候并不会去执行,只有当我们真正调用的时候才会去执行Lambda表达式.当BService去注入AService属性的时候,我们已经事先把这个原始对象存放到了三级缓存中,所以BService在单例池找不到,最终会在三级缓存中找到,这个Lambda式,所以我们只要执行这个Lambda表达式就行了:
注意:
当执行这个Lambda式的时候就要看有没有配置AOP,如果配置了AOP的话,执行Lambda表达式生成的对象就是一个代理对象,如果没有配置AOP,那么执行Lambda表达式就会返回原始对象.(当然上面说说的步骤都是基于循环依赖的情况的,如果没有出现循环依赖BService根本就不需要去寻找AService,那么这个三级缓存中的Lambda式也就没有用到)
清楚了执行Lambda表达式就会得到原始对象或者代理对象,那么到底怎么执行的呢?
进入Lambda式的方法内部看一下:
下面代码可以看到真正执行Lambda式的是***SmartInstantiationAwareBeanPostProcessor***这样一个Bean的后置处理器接口.
//存入三级缓存中的Lambda式方法 getEarlyBeanReference(beanName, mbd, bean)
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//可以看到这里也在进行对后置处理器的循环
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//判断是不是属于该后置处理器,
// SmartInstantiationAwareBeanPostProcessor后置处理器是一个接口,
//该接口有一个实现类就是专门用于处理AOP的一个实现类:AbstractAutoProxyCreator
//当我们执行Lambda表达式的时候该处理AOP的实现类就会帮帮我们执行AOP的逻辑创建代理对象
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//执行Lambda表达式
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
进入到***SmartInstantiationAwareBeanPostProcessor***后置处理器接口的***getEarlyBeanReference(exposedObject, beanName)***方法,
你会返现这里面直接默认返回的是原始Bean对象,这也是为什么没有配置AOP就会返回原始对象的原因!
那么AOP的逻辑在哪里呢?
其实注释你也能看到***SmartInstantiationAwareBeanPostProcessor***后置处理器接口有一个实现类***AbstractAutoProxyCreator***这个实现类看名字就知道是用来实现动态代理的!!!
(心情有些激动:借用李云龙的一句话:你真他娘的是个天才!)
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
//你会发现这个方法有两个实现类重写了该方法:AbstractAutoProxyCreator和InstantiationAwareBeanPostProcessorAdapter
//可以看出第一个实现类就是在配置AOP的情况下去执行的覆盖方法
return bean;
}
我们进入到AbstractAutoProxyCreator的getEarlyBeanReference(exposedObject, beanName) 方法看一下源码.
可以看到 wrapIfNecessary(bean, beanName, cacheKey) 就是在执行动态代理
这行代码前面还有一行 this.earlyProxyReferences.put(cacheKey, bean); 这行代码把我们要进行动态代理的原始对象放了进去,很明显这玩意儿是个Map集合:
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
那么存放它有什么用呢?
我们看完动态代理的逻辑代码再说
/**
* 具体配置了AOP后执行Lambda表达式的逻辑代码--lk,提前进行AOP会走这个方法
* @MethodName: getEarlyBeanReference
* @param bean
* @param beanName
* @return: java.lang.Object
*/
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//这一个步骤也很关键,我们可以看到这个Map是将我们需要进行AOP的原始对象放了进去(就是将我们提前进行AOP的原始对象放了进去)
this.earlyProxyReferences.put(cacheKey, bean);
//开始专门进行AOP的逻辑
return wrapIfNecessary(bean, beanName, cacheKey);
}
看一下 wrapIfNecessary(bean, beanName, cacheKey) 内部的逻辑代码,
可以看到确实执行了动态代理返回了代理对象.
//具体执行代理逻辑
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//1 判断是不是需要代理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//创建代理对象如果需要代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//基于原始对象创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
//将此代理对象返回
return bean;
}
我们上面说到***this.earlyProxyReferences.put(cacheKey, bean);***这行代码有什么作用.
那么我们可以回头看一下上面流程图,我们在初始化之后要在Bean的后置处理器的初始化后方法中判断是不是配置了AOP,是不是已经进行了AOP,那么这个map集合到了初始化后方法就能用上了,
因为我们知道AbstractAutoProxyCreator其实也是一个Bean的后置处理器,当配置了AOP之后,一定会进入到它的***初始化后方法***.
进入AbstractAutoProxyCreator的初始化后方法看一下:
可以看到在第二个if分支里面我们从earlyProxyReferences这个Map集合中重新根据BeanName获取出来一个原始Bean对象,并进行判断: 如果与传入进来的不相等证明之前没有提前进行AOP,如果相等,证明已经提前进行了AOP就直接返回即可,如果不相等,就去执行动态代理生成代理对象返回.
//AbstractAutoProxyCreator的初始化后方法
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//从缓存中获取出来,根据BeanName寻找
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//根据cacheKey从保存 提前进行AOP的map中 找,如果提前进行AOP的map中找到的原始对象和我们传进来的Bean(其实也是原始对象)相同,
// 就证明已经提前进行了AOP就会直接return Bean
//如果不同,证明没有进行提前AOP,就会走下面分支进行AOP,当然我们进行AOP的前提是我们配置并启用了AOP
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//进行AOP
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
//直接返回,不进行AOP的原始对象,上面的if条件顺利解决了是否已经提前进行了AOP的操作
return bean;
}
11.3 问题思考
同样问题思考,在上面循环依赖中出现了AOP,
我们也是只利用了一级缓存singletonObjects和三级缓存objectFactories,最终也没有使用到三级缓存earlySingletonObjects;那么不使用二级缓存会出现什么问题呢?二级缓存到底有什么作用呢?
12 如果三个Bean之间出现循环依赖如何解决?
带着11.3的问题,我们来分析一下只使用一级缓存和三级缓存可能出现的问题:
当我们有第三个CService这时候也需要注入AService属性:试想一下
当BService执行属性注入的时候拿到Lambda表达式并执行获取到AService的代理对象,完成属性注入,最终BService放入单例池中。
此时开始去执行CService的生命周期,也需要注入AService属性,这时候因为AService还在创建中,所以CService最终也会在三级缓存中拿到一个Lambda表达式执行得到一个AService的代理对象完成属性注入,最终CService放入到单例池。
最后回过头来去完成AService的生命周期。
此时问题就出现了:BService中注入到aService属性的代理对象和CService中注入到aService属性的代理对象并不是同一个代理对象!!!!!
12.1 问题解决
这时候就用到我们的二级缓存earlySingletonObjects
解决思路:
我们只需要当我们在三级缓存中执行Lambda表达式获取到的对象之后(代理对象或者原始对象)放入到我们的二级缓存中,然后再将三级缓存中存放原始对象的Lambda表达式删除即可。
然后在寻找对象的流程中在一级缓存和三级缓存之间加一个二级缓存即可。这样CService在寻找的时候就会直接从二级缓存中拿到代理对象,直接完成属性注入,保证了两个两个代理对象一样.
流程图变为:
具体流程不再文字详述了,就是注入属性的时候寻找对象的流程变为先从一级缓存单例池 中找,找不到去二级缓存earlySingleObjects中找,如果还找不到就去三级缓存objectFactories中执行Lambda表达式生成一个代理对象或者普通对象,然后放入到二级缓存中,最后将对应Lambda表达式从三级缓存中删除.
下面是从三级缓存中寻找对象的逻辑代码可以看一下:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
//先从单例池里面去找
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例池里没有找到,并且该对象还在创建过程中,进入下面分支,从二级或者三级缓存中寻找
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//从二级缓存中寻找
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//从三级缓存中寻找,寻找到了进入下面分支
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//获取需要进行AOP代理里面的原始对象,这里就会去执行Lambda表达式
singletonObject = singletonFactory.getObject();
//放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
13 出现AOP的循环依赖中创建的代理对象什么时候放到单例池呢?
我们看一下在doCreateBean()方法中有这样一段代码
这段代码如果提前暴漏了就会进到if分支,后面会从三个缓存中寻找,如果之前已经有循环依赖并且配置了AOP就会从二级缓存中找到代理对象,最终***exposedObject = earlySingletonReference;**这行代码就完成了替换,最终放入单例池.
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 2:实例化:...
// 3: 实例化后:...
// 开始填充属性...
//4:初始化,实例化后开始进行初始化,...
//可以看到只要提前暴漏了就会进入到这里
if (earlySingletonExposure) {
//从三个缓存(三级缓存)中寻找
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//如果提前暴露的对象和经过了完整生命周期的Bean对象exposedObject和原始对象bean相等则进入分支,把代理对象赋值给exposedObject
//然后将exposedObject返回放到单例池中
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
//....
return exposedObject;
}
14 Spring整合Mybatis的简单原理
这里为了跟前面讲解FactoryBean整合Mybatis呼应上,所以做一个代码的板书看一看FactoryBean是如何完成与Mybatis的整合的
首先我们得知道,Spring整合Mybatis的最终目的是什么?
就是让Spring去管理Mybatis生成的代理对象,但是Spring管理经历了Spring完成生命周期的Bean对象,也就是放入到单例池中的Bean对象,所以我们的最终目的就是将Mybatis生成的代理对象放到单例池即可.
14.1 创建FactoryBean将Mybatis的代理对象创建成Bean
代码如下
/**
* 用于自定义Bean 我们这里是用它来完成Mybatis与Spring整合原理学习
* 我们的Mybatis整合的第二种方式就可以通过这种方式来完成;
* 注意:泛型必须得写
* <p>
* 这个FactoryBean是一个很神奇的存在,它可以生成一类的对象,有点"指鹿为马"的哪种感觉,就像我们用FactoryBean生成了一个普通的对象Person
* 当Spring通过MyTestFactoryBean的类型去找时会返回它生成的对象Person,同样通过myTestFactoryBean名字找也是一样返回它真正生成的对象
* 也就是getObject()方法返回的对象
*/
// @Component这个注解不能加,因为在MyTestBeanDefinitionRegisterar中已经将此类添加到BeanDefinition中了,所以不需要加@Component注解了
public class MyTestFactoryBean implements FactoryBean<Object> {
private Class<?> mapper;
public MyTestFactoryBean(Class<?> mapper) {
this.mapper = mapper;
}
/**
* 当我们通过ApplicationContext.getBean的时候会返回我们的对象,并且这个方法 只会调用一次
*
* @param
* @MethodName: getObject
* @return: java.lang.Object
*/
@Override
public Object getObject() throws Exception {
//模拟Mybatis生成的Mapper的代理对象
Object o = Proxy.newProxyInstance(MyTestFactoryBean.class.getClassLoader(), new Class<?>[]{mapper}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName());
return null;
}
});
return o;
// return new Person();
}
/**
* 返回对象类型
*
* @param
* @MethodName: getObjectType
* @return: java.lang.Class<?>
*/
@Override
public Class<?> getObjectType() {
return mapper;
}
}
14.2 创建BeanDefinition注册器
用于将上一步的FactoryBean封装到BeanDefinition中最终将FactoryBean也注册成Bean,
这样就等于我们的Mybatis代理对象也注册成了Bean
需要实现***ImportBeanDefinitionRegistrar***接口,这个接口就是专门用于注册BeanDefinition的.
/**
* 用于实现Spring整合Myabtis的原理
* 我们在Spring中可以使用@Autowired注解来注入我们Mybatis的Mapper
* (如在TestBeanService中输入UserMapper和OrderMapper)
* 考虑一下可以知道,既然可以使用注解注入进去证明我们的Mapper其实是一个经历了
* Spring完整生命周期的Bean,但是Mapper是由Mybatis生成的代理对象,它并不是我们Spring自己生成的,
* 那么怎么才能让这个Mybatis生成的代理对象经历完整的Bean的生命周期呢?
* 这就要看Mybatis整合Spring的实现原理了:()
* 我们可以实现FactoryBean接口,通过FactoryBean来生成的Mapper接口的代理对象,并交给Spring进行管理.
* 并使用ImportBeanDefinitionRegistrar接口来注册我们我们的BeanDefinition,让我们的代理对象经历完整的Spring的生命周期;
* 这样代理对象就能被我们的Spring项目管理了
*
* @ProjectName: spring
* @ClassName: MyTestBeanDefinitionRegistrar
* @Author: MrKay
* @Date: 2021/6/12
*/
public class MyTestBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//获取MapperScan注解的所有属性信息
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(MyMapperScan.class.getName());
Object value = annotationAttributes.get("value");
System.out.println(value);//show.mrkay.mapper
//TODO 可以看到包路径都拿到了所以我们可以根据包路径获取包里面所有的接口就不需要进行下面的模拟数据了
//模拟数据
List<Class<?>> mapperds = new ArrayList<>();
mapperds.add(UserMapper.class);
mapperds.add(OrderMapper.class);
for (Class<?> mapper : mapperds) {
//获取BeanDefinition构造器
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
//向BeanDefinition中添加BeanCalss
//正好利用我们的FactoryBean可以生成一类的对象
beanDefinition.setBeanClass(MyTestFactoryBean.class);
//指定使用构造方法,指定构造方法需要传递的参数
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(mapper);
//注册我们的BeanDefinition,让Spring来完成完成的生命周期
registry.registerBeanDefinition(mapper.getSimpleName(), beanDefinition);
}
}
}
14.3 模拟Mybatis的@MapperScan注解
代码如下:
可以看到***@Import***注解在这里用到了,他就是将***MyTestBeanDefinitionRegistrar***导入到了单例池中
/**
* 自定义模仿Mybatis的MapperScan注解
*/
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Import(MyTestBeanDefinitionRegistrar.class)//导入注册我们的BeanDefinition
public @interface MyMapperScan {
/**
* 默认值为""
*/
String value() default "";
}
14.4 测试结果
截图如下:我们看一下TestBeanService的两个属性Usermapper和OrderMapper是不是注入成功,并且是个代理对象就可以了.可以看出确实是一个代理对象
15 总结
没啥说的,对Spring源码的学习感受只有一个字:
难!!!