Spring的Bean的生命周期【上】
1.关于spring的FactoryBean的问题:
@Component()
public class LubanFactoryBean implements FactoryBean {
public Object getObject() throws Exception {
return new User();
}
public Class<?> getObjectType() {
return User.class;
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(applicationContext.getBean("lubanFactoryBean"));
System.out.println(applicationContext.getBean("lubanFactoryBean"));
System.out.println(applicationContext.getBean("lubanFactoryBean"));
}
}
com.luban.entity.User@5aaa6d82
com.luban.entity.User@5aaa6d82
com.luban.entity.User@5aaa6d82
问题1:getBean的时候,为什么get的对象对象都是同一个对象呢?
default boolean isSingleton() {
return true;
}
FactoryBean有一个default方法:isSingleton,默认是单例
那么我们就知道虽然getBean了三次,但是getObject()就只执行了一次
问题2:那么在执行getObject()的时候是在哪一行代码呢
应该是在第一次调用getBean()的时候执行的
那么在启动spring的时候,做些什么呢?
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
我们在启动spring的时候,就会去创建非懒加载的单例bean
我们的LubanFactoryBean上面有一个@Componet,Spring启动的时候就去扫描,并把它当作普通的
bean,所以在执行完这行代码之后,我们在单例池中有LubanFactoryBean
我们看到这个LubanFactoryBeanDefinition是通过扫描得到的
问题3:为什么往单例池放数据的时候是LubanFactoryBean,在getBean的时候却是User呢?
流程:在getBean的时候,会把beanName转化为一种eg:lubanFactoryBean,然后在单例池中找到这个对象
LubanFactoryBean,然后判断这个对象是不是FactoryBean,不是直接返回,是则从一个缓存map中去拿,如果缓存map不存在这个对象,就强制转换为FactoryBean,然后调用getObject方法,放到缓存map里面。
我们点击getBean的源码进去看 (实现类:AbstactBeanFctory)
---------------------------------transformedBeanName-----------------------------------
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 对beanName进行转换 name如果是"&lubanFactoryBean",那么beanName就是"lubanFactoryBean"
final String beanName = transformedBeanName(name);
Object bean;
//这个方法的作用就是 不管你传过来的name:lubanFactoryBean,lubanFactoryBean1(别名),&lubanFactoryBean,一律转化为lubanFactoryBean,因为我要用它来进行获取单例池中的对象(此例:LubanFactoryBean对象)
--------------------------- transformedBeanName(name)转换beanName-----------------------
* 返回beanName,去掉FactoryBean的&前缀,并且把name当做别名去aliasMap中寻找原始的beanName
*/
protected String transformedBeanName(String name) { // &lubanFactoryBean lubanFactoryBean1 user1 &beanName
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
----------------------------- doGetBean-----------------------------------------------
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 对beanName进行转换 name如果是"&lubanFactoryBean",那么beanName就是"lubanFactoryBean"
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//从单例池中去拿,此时beanName:ubanFactoryBean,那么肯定可以拿到对象LubanFactoryBean
Object sharedInstance = getSingleton(beanName); // Map<>
if (sharedInstance != null && args == null) {
// 判断sharedInstance是不是FactoryBean,如果是FactoryBean,那么真正需要拿到的是getObject方法所返回的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
---------------------------getObjectForBeanInstance-判断是不是FactoryBean--------------
// 判断beanInstance是不是FactoryBean
// 如果是FactoryBean
// 如果name是以&开头,那么则返回beanInstance
// 如果name不是以&开头,那么返回的是getObject方法中所返回的对象(注意如果是单例,则会进行缓存)
// 如果不是FactoryBean,那么返回的是beanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果是&lubanFactoryBean,那么则直接返回单例池(SingletonObjects)中的对象
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
//如果不是FactoryBean,直接返回.
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 如果beanInstance是FactoryBean,并且name也不是以&开头
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
// 从factoryBeanObjectCache中没有拿到则进行创建
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 调用getObject方法得到对象并放入factoryBeanObjectCache中
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
-----------------------getCachedObjectForFactoryBean----------------------
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}//factoryBeanObjectCache是一个cocurretHashMap,一开始getBean的时候肯定没有
//就会走下面的逻辑,首先把beanInstance强制转化为FactoryBean,这样我们可以调用getObject方法,
---------------------------getObjectFromFactoryBean------------------------------
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {//factory就是LubanFactoryBean,默认isSingleton()为true
// 是不是单例的
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 调用getObject方法得到一个对象
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
----------------------------------doGetObjectFromFactoryBean--------------------------
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();//是单例就直接去调用FactoryBean的getobject()方法
}
-------------------------------doGetObjectFromFactoryBean----------------------------
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
// 单例真正创建
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
// 调用BeanPostProcessor执行初始化后的逻辑,主要就是进行AOP
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
**************************//放入到我们的factoryBeanObjectCache(cocurrentHashMap)中
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 多例
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
问题4:FactoryBean用在哪儿呢?
Spring整合mybatis的时候就可以使用FactoryBean
我们在getObject中就可以把Mapper的一个实现类加入到我们spring的容器里面了,
但是这种方式和@Bean,又什么区别呢?
我们的@Bean只能是在某个方法上,加上@Bean,但是如果一个类实现了@FactoryBean,它也可以实现其他的接口,
@Component()
public class LubanFactoryBean implements FactoryBean, BeanClassLoaderAware {
public Object getObject() throws Exception {
return new User();
}
public Class<?> getObjectType() {
return User.class;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
}
}
我们的FactoryBean比@Bean更加的强大一些。
问题5:ApplicationContext为什么实现了BeanFactory,在其内部还存在DefaultListableBeanFactory
最重要的就是BeanFctory:
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
如果我们实现了某个接口,就代表着我们要实现它的方法,那么ApplicationContext是怎么实现它的这些方法的呢,调用DefaultListableBeanFactory,因为这个DefaultListableBeanFactory功能已经很强大了,所以我只要调用它的方法就好了,是一种委托。
2.Spring的生命周期
进行扫描–>生成BeanDefinition–>合并BeanDefinition–>加载类–>实例化前–>推断构造方法–>实例化
问题1:进行扫描
如果让你进行扫描,你会怎么做?
1.Spring进行扫描的时候不会加载,生成class文件,而是使用asm直接去判断字节码
2.生成BeanDefinition
-----------refresh();----------------------
----------- // 完成beanFactory的初始化(实例化非懒加载的单例bean)
finishBeanFactoryInitialization(beanFactory);--------------------------
//实例化所有非懒加载的bean,也就是怎么来创建bean
----------beanFactory.preInstantiateSingletons();----------------------------
我们来看一下继承的BeanDefinition
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="parent" scope="prototype" abstract="true"></bean>
<bean id="userService" class="com.luban.service.UserService" parent="parent"></bean>
</beans>
//我们来验证获得的userService是不是原型
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userService"));
}
}
com.luban.service.UserService@5387f9e0
com.luban.service.UserService@6e5e91e4
com.luban.service.UserService@2cdf8d8a
此时在beanDefinitionMap中是GenericBeanDefinition类型,是根据bean的属性来进行生成的
在mergeBeanDefinitions就是RootBeanDefininiton类型,是GenericBeanDefinition合并得到的
我们可以看一下它们各自是什么BeanDefinition
在beanDefinitionMap的时候类型是:GenericBeanDefinition,这个可以设置它们的ParentName
@Override
public void setParentName(@Nullable String parentName) {
this.parentName = parentName;
}
@Override
@Nullable
public String getParentName() {
return this.parentName;
}
在合并之后得到的(mergeBeanDefinitions)是RootBeanDefinition,setParentName是时候会报错,就不再又ParentBeanDefinition
@Override
public String getParentName() {
return null;
}
@Override
public void setParentName(@Nullable String parentName) {
if (parentName != null) {
throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
}
}
源码:是怎么样获得RootBeanDefinition
--------------------preInstantiateSingletons----------------------------------
@Override
public void preInstantiateSingletons() throws BeansException {
//获取所有的beanNames
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 循环bd,实例化单例bean
for (String beanName : beanNames) { // userService
// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
-----------------getMergedLocalBeanDefinition(beanName)-----------------------------
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}//如果mergedBeanDefinitions存在直接返回,否则遍历beanDefinitionMap进行合并
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
-----------------父bd和子bd进行合并---------------------------------------------------------
------getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException--------------------------------------
if (mbd == null || mbd.stale) {
previous = mbd;
// 如果bd的父bd为空,那么就直接把bd封装为RootBeanDefinition
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
// RootBeanDefinition没有父BeanDefinition
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {//如果父bd不为空,那就递归的去获取<bean abstact=true>的bean
BeanDefinition pbd;
try {
// 父bd的beanName
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
//把子bd的属性赋值给父属性
// pbd表示父BeanDefinition, bd表示本BeanDefinition
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd); // 把bd的属性设置给mbd, 而mbd是基于pbd来的,pbd是parent,bd是当前bd,把当前bd的属性设置给pbd就是合并(合并属性)
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
// 如果某个<bean/>内包含了一个内部<bean/>,containingBd表示外部bean, mbd表示内部bean
// 外部bean如果不是单例bean,内部bean是单例的,那么则把内部bean的scope设置为和外部bean的scope一样的
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
***********************************合并完成就放入到mergedBeanDefinitions中*****************
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
继续往下走逻辑:
根据BeanName去创建Bean:
// 非抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是不是一个SmartFactoryBean
if (isFactoryBean(beanName)) {
// 如果是一个FactoryBean,那么则获取LubanFactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// eager:急切的意思,立马初始化
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) {
// 根据beanName去生成FactoryBean中所生成的Bean对象
getBean(beanName);
}
}
}
else {
// 根据beanName去创建bean
getBean(beanName);
}
}
public class LubanFactoryBean1 implements SmartFactoryBean {
@Override
public Object getObject() throws Exception {
return null;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isEagerInit() {//return false的时候,跟FactoryBean没什么区别
// return true的时候就不是懒加载了
return false;
}
}
在getBean的时候就是去创建Bean,
点击进去getBean看源码:
在doGetBean中流程:
首先获取到合并的beanDefinition对象,然后看对象是否存在循环依赖,没有循环依赖有DependOn的时候就
先去创建依赖的哪个对象
创建bean解决循环依赖的问题:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
try {
// 得到合并后的BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//循环依赖**************
// 加载DependsOn的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 判断beanName是不是也被dep依赖了,如果是,就是相互依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//在isDependent(beanName,dep)中:存在了两个map进行判断是不是存在循环依赖
// 存在在两个map中
// 1. dependentBeanMap,key为dep, value是一个LinkedHashSet,表示dep被哪些bean依赖了
// 2. dependenciesForBeanMap,key为beanName,value是一个LinkedHashSet,表示beanName依赖了哪些bean
}
registerDependentBean(dep, beanName);
try {
// 先去生成所依赖的bean
getBean(dep); // getBean("xxx")
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
创建bean解决Scope的问题:
if (mbd.isSingleton()) {
// 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// sharedInstance可能是一个FactoryBean,所以需要单独再去 factoryBeanObjectCache中去获取对应的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);//记录一下开始产生bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);//记录产生bean结束,主要是为了循环依赖
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
CreateBean方法 BeanPostProcessor
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 1、实例化前 null
Object bean = ***resolveBeforeInstantiation(beanName, mbdToUse); // 对象
if (bean != null) {
return bean;
}
}
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
try {
// 创建bean Spring自带的创建bean的方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
其实resolveBeforeInstantiation就是给我们程序员一个扩展,bean!=null,就不需要去执行Spring自带
的创建bean的方法,那么我们怎么去扩展呢?
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// beforeInstantiationResolved为null或true
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;
}
在这个实例化前
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
我们可以去获取到InstantiationAwareBeanPostProcessor类型的后置处理器,调用postProcessBeforeInstantiation的方法,产生对象,这样bean!=null.我们就不用去执行Spring的create逻辑了