归志宁无五亩园,读书本意在元元。这篇文章主要讲述Spring框架系列 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)相关的知识,希望能为你提供帮助。
引入
上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个??ConcurrentHashMap< String, Object> ?
?;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文主要研究的内容?@pdai
本文主要研究如何从IOC容器已有的BeanDefinition信息,实例化出Bean对象;这里还会包括三块重点内容:
上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个??ConcurrentHashMap< String, Object> ?
?;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢?
- BeanFactory中getBean的主体思路
- Spring如何解决循环依赖问题
- Spring中Bean的生命周期
BeanFactory中getBean的主体思路
上文中我们知道BeanFactory定义了Bean容器的规范,其中包含根据bean的名字, Class类型和参数等来得到bean实例。
// 根据bean的名字和Class类型等来得到bean实例
Object (String name)BeansException;
Object (String name, Class requiredType)BeansException;
Object (String name, Object... args)BeansException;
< T> T (Class< T> requiredType)BeansException;
< T> T (Class< T> requiredType, Object... args)BeansException;
初步的思考
上文我们已经分析了IoC初始化的流程,最终的将Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个?
?ConcurrentHashMap<
String, Object>
?
?;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等;这样我们初步有了实现?
?Object getBean(String name)?
?这个方法的思路:- 从beanDefinitionMap通过beanName获得BeanDefinition
- 从BeanDefinition中获得beanClassName
- 通过反射初始化beanClassName的实例instance
- 构造函数从BeanDefinition的getConstructorArgumentValues()方法获取
- 属性值从BeanDefinition的getPropertyValues()方法获取
- 返回beanName的实例instance
(PS:如上只是我们初步的思路,而Spring还需要考虑各种设计上的问题,比如beanDefinition中其它定义,循环依赖等;所以我们来看下Spring是如何是如何实现的)
Spring中getBean的主体思路
BeanFactory实现getBean方法在AbstractBeanFactory中,这个方法重载都是调用doGetBean方法进行实现的:
Object (String name)BeansException
doGetBean(name, , , );
< T> T (String name, Class< T> requiredType)BeansException
doGetBean(name, requiredType, , );
Object (String name, Object... args)BeansException
doGetBean(name, , args, );
< T> T (String name, @Nullable Class< T> requiredType, @Nullable Object... args)
BeansException
doGetBean(name, requiredType, args, );
我们来看下doGetBean方法(这个方法很长,我们主要看它的整体思路和设计要点):
// 参数typeCheckOnly:bean实例是否包含一个类型检查
< T> T (
String name, @Nullable Class< T> requiredType, @Nullable Object[] args,typeCheckOnly)
BeansException
// 解析bean的真正name,如果bean是工厂类,name前缀会加& ,需要去掉
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
(sharedInstance !=& & args == )
// 无参单例从缓存中获取
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, );
// 如果bean实例还在创建中,则直接抛出异常
(isPrototypeCurrentlyInCreation(beanName))
BeanCurrentlyInCreationException(beanName);
// 如果 bean definition 存在于父的bean工厂中,委派给父Bean工厂获取
BeanFactory parentBeanFactory = getParentBeanFactory();
(parentBeanFactory !=& & !containsBeanDefinition(beanName))
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
(parentBeanFactoryAbstractBeanFactory)
((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
(args != )
// Delegation to parent with explicit args.
(T) parentBeanFactory.getBean(nameToLookup, args);
(requiredType != )
// No args -> delegate to standard getBean method.
parentBeanFactory.getBean(nameToLookup, requiredType);
(T) parentBeanFactory.getBean(nameToLookup);
(!typeCheckOnly)
// 将当前bean实例放入alreadyCreated集合里,标识这个bean准备创建了
markBeanAsCreated(beanName);
StartupStep beanCreation = .applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
(requiredType != )
beanCreation.tag("beanType", requiredType::toString);
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保它的依赖也被初始化了.
String[] dependsOn = mbd.getDependsOn();
(dependsOn != )
(String dep : dependsOn)
(isDependent(beanName, dep))
BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between " + beanName + " and " + dep + "");
registerDependentBean(dep, beanName);
getBean(dep); // 初始化它依赖的Bean
(NoSuchBeanDefinitionException ex)
BeanCreationException(mbd.getResourceDescription(), beanName,
"" + beanName + " depends on missing bean " + dep + "", ex);
// 创建Bean实例:单例
(mbd.isSingleton())
sharedInstance = getSingleton(beanName, () ->
// 真正创建bean的方法
createBean(beanName, mbd, args);
(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);
ex;
);
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
// 创建Bean实例:原型
(mbd.isPrototype())
// Its a prototype -> create a new instance.
Object prototypeInstance = ;
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
afterPrototypeCreation(beanName);
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
// 创建Bean实例:根据bean的scope创建
String scopeName = mbd.getScope();
(!StringUtils.hasLength(scopeName))
IllegalStateException("No scope name defined for bean ′" + beanName + "");
Scope scope = .scopes.get(scopeName);
(scope == )
IllegalStateException("No Scope registered for scope name " + scopeName + "");
Object scopedInstance = scope.get(beanName, () ->
beforePrototypeCreation(beanName);
createBean(beanName, mbd, args);
afterPrototypeCreation(beanName);
);
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
(IllegalStateException ex)
ScopeNotActiveException(beanName, scopeName, ex);
(BeansException ex)
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
ex;
beanCreation.end();
adaptBeanInstance(name, beanInstance, requiredType);
这段代码很长,主要看我加中文注释的方法即可。
- 解析bean的真正name,如果bean是工厂类,name前缀会加& ,需要去掉
- 无参单例先从缓存中尝试获取
- 如果bean实例还在创建中,则直接抛出异常
- 如果bean definition 存在于父的bean工厂中,委派给父Bean工厂获取
- 标记这个beanName的实例正在创建
- 确保它的依赖也被初始化
- 真正创建
- 单例时
- 原型时
- 根据bean的scope创建
Spring单例模式下的属性依赖
首先我们需要说明,Spring只是解决了单例模式下属性依赖的循环问题;Spring为了解决单例的循环依赖问题,使用了三级缓存。
先来看下这三级缓存
/** Cache of singleton objects: bean name --> bean instance */
Map< String, Object> singletonObjects =ConcurrentHashMap< String, Object> (256);
/** Cache of early singleton objects: bean name --> bean instance */
Map< String, Object> earlySingletonObjects =HashMap< String, Object> (16);
/** Cache of singleton factories: bean name --> ObjectFactory */
Map< String, ObjectFactory< ?> > singletonFactories =HashMap< String, ObjectFactory< ?> > (16);
- 第一层缓存(singletonObjects):单例对象缓存池,已经实例化并且属性赋值,这里的对象是成熟对象;
- 第二层缓存(earlySingletonObjects):单例对象缓存池,已经实例化但尚未属性赋值,这里的对象是半成品对象;
- 第三层缓存(singletonFactories): 单例工厂的缓存
Object (String beanName,allowEarlyReference)
// Spring首先从singletonObjects(一级缓存)中尝试获取
Object singletonObject = .singletonObjects.get(beanName);
// 若是获取不到而且对象在建立中,则尝试从earlySingletonObjects(二级缓存)中获取
(singletonObject ==& & isSingletonCurrentlyInCreation(beanName))
(.singletonObjects)
singletonObject = .earlySingletonObjects.get(beanName);
(singletonObject ==& & allowEarlyReference)
ObjectFactory< ?> singletonFactory = .singletonFactories.get(beanName);
(singletonFactory != )
//若是仍是获取不到而且容许从singletonFactories经过getObject获取,则经过singletonFactory.getObject()(三级缓存)获取
singletonObject = singletonFactory.getObject();
//若是获取到了则将singletonObject放入到earlySingletonObjects,也就是将三级缓存提高到二级缓存中
.earlySingletonObjects.put(beanName, singletonObject);
.singletonFactories.remove(beanName);
(singletonObject != NULL_OBJECT ? singletonObject : );
补充一些方法和参数
- ?
?isSingletonCurrentlyInCreation()?
?:判断当前单例bean是否正在建立中,也就是没有初始化完成(好比A的构造器依赖了B对象因此得先去建立B对象, 或则在A的populateBean过程当中依赖了B对象,得先去建立B对象,这时的A就是处于建立中的状态。) - ?
?allowEarlyReference?
? :是否容许从singletonFactories中经过getObject拿到对象
从上面三级缓存的分析,咱们能够知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。这个cache的类型是ObjectFactory,定义以下:
< >
T ()BeansException;
在bean建立过程当中,有两处比较重要的匿名内部类实现了该接口。一处是Spring利用其建立bean的时候,另外一处就是:
addSingletonFactory(beanName,ObjectFactory< Object> ()
@OverrideObject ()BeansException
getEarlyBeanReference(beanName, mbd, bean);
);
此处就是解决循环依赖的关键,这段代码发生在createBeanInstance以后,也就是说单例对象此时已经被建立出来的。这个对象已经被生产出来了,虽然还不完美(尚未进行初始化的第二步和第三步),可是已经能被人认出来了(根据对象引用能定位到堆中的对象),因此Spring此时将这个对象提早曝光出来让你们认识,让你们使用。
好比“A对象setter依赖B对象,B对象setter依赖A对象”,A首先完成了初始化的第一步,而且将本身提早曝光到singletonFactories中,此时进行初始化的第二步,发现本身依赖对象B,此时就尝试去get(B),发现B尚未被create,因此走create流程,B在初始化第一步的时候发现本身依赖了对象A,因而尝试get(A),尝试一级缓存singletonObjects(确定没有,由于A还没初始化彻底),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,因为A经过ObjectFactory将本身提早曝光了,因此B可以经过ObjectFactory.getObject拿到A对象(半成品),B拿到A对象后顺利完成了初始化阶段一、二、三,彻底初始化以后将本身放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成本身的初始化阶段二、三,最终A也完成了初始化,进去了一级缓存singletonObjects中,并且更加幸运的是,因为B拿到了A的对象引用,因此B如今hold住的A对象完成了初始化。
Spring为何不能解决非单例属性之外的循环依赖?
Spring为什么不能解决构造器的循环依赖?构造器注入形成的循环依赖: 也就是beanB需要在beanA的构造函数中完成初始化,beanA也需要在beanB的构造函数中完成初始化,这种情况的结果就是两个bean都不能完成初始化,循环依赖难以解决。
通过以下几个问题,辅助我们进一步理解。
Spring解决循环依赖主要是依赖三级缓存,但是的在调用构造方法之前还未将其放入三级缓存之中,因此后续的依赖调用构造方法的时候并不能从三级缓存中获取到依赖的Bean,因此不能解决。
Spring为什么不能解决prototype作用域循环依赖?这种循环依赖同样无法解决,因为spring不会缓存‘prototype’作用域的bean,而spring中循环依赖的解决正是通过缓存来实现的。
Spring为什么不能解决多例的循环依赖?多实例Bean是每次调用一次getBean都会执行一次构造方法并且给属性赋值,根本没有三级缓存,因此不能解决循环依赖。
那么其它循环依赖如何解决?
那么实际开发中,类似的依赖是如何解决?
- 生成代理对象产生的循环依赖
- 使用@Lazy注解,延迟加载
- 使用@DependsOn注解,指定加载先后关系
- 修改文件名称,改变循环依赖类的加载顺序
- 使用@DependsOn产生的循环依赖
- 多例循环依赖
- 构造器循环依赖
重点:Spring中Bean的生命周期
Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。
Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
【Spring框架系列 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)】而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
Spring Bean生命周期流程
Spring 容器中 Bean 的生命周期流程
在 Spring 中,Bean 的生命周期是一个很复杂的执行过程,我们可以利用 Spring 提供的方法定制 Bean 的创建过程。
- 如果 BeanFactoryPostProcessor 和 Bean 关联, 则调用postProcessBeanFactory方法.(即首先尝试从Bean工厂中获取Bean)
- 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessBeforeInstantiation方法
- 根据配置情况调用 Bean 构造方法实例化 Bean。
- 利用依赖注入完成 Bean 中所有属性值的配置注入。
- 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessAfterInstantiation方法和postProcessProperties
- 调用xxxAware接口 (上图只是给了几个例子)
- 第一类Aware接口
- 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,则 Spring 调用 setBeanClassLoader() 方法传入classLoader的引用。
- 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
- 第二类Aware接口
- 如果 Bean 实现了 EnvironmentAware 接口,则 Spring 调用 setEnvironment() 方法传入当前 Environment 实例的引用。
- 如果 Bean 实现了 EmbeddedValueResolverAware 接口,则 Spring 调用 setEmbeddedValueResolver() 方法传入当前 StringValueResolver 实例的引用。
- 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
- ...
- 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
- 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。(或者有执行@PostConstruct注解的方法)
- 如果在配置文件中通过init-method 属性指定了初始化方法,则调用该初始化方法。
- 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
- 如果在
< bean>
中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在< bean>
中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。 - 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;(或者有执行@PreDestroy注解的方法)
- 如果在配置文件中通过destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
- Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中
< bean>
的init-method和destroy-method指定的方法 - Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、ApplicationContextAware;当然也包括InitializingBean和DiposableBean这些接口的方法(可以被@PostConstruct和@PreDestroy注解替代)
- 容器级生命周期接口方法: 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
- 工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
定义Bean(这里是User), 并让它实现BeanNameAware,BeanFactoryAware,ApplicationContextAware接口和InitializingBean,DisposableBean接口:
我们通过一个例子来验证上面的整个流程
tech.pdai.springframework.entity;
lombok.ToString;
lombok.extern.slf4j.Slf4j;
org.springframework.beans.BeansException;
org.springframework.beans.factory.BeanFactory;
org.springframework.beans.factory.BeanFactoryAware;
org.springframework.beans.factory.BeanNameAware;
org.springframework.beans.factory.DisposableBean;
org.springframework.beans.factory.InitializingBean;
org.springframework.context.ApplicationContext;
org.springframework.context.ApplicationContextAware;
/**
* @author pdai
*/
@Slf4j
@ToString
, , ,
,
/**
* users name.
*/
String name;
/**
* users age.
*/
age;
/**
* bean factory.
*/
BeanFactory beanFactory;
/**
* application context.
*/
ApplicationContext applicationContext;
/**
* bean name.
*/
String beanName;
()
log.info("execute User#new User()");
(String name)
log.info("execute User#setName()", name);
.name = name;
( age)
log.info("execute User#setAge()", age);
.age = age;
@Override
(BeanFactory beanFactory)BeansException
log.info("execute BeanFactoryAware#setBeanFactory");
.beanFactory = beanFactory;
@Override
(String s)
log.info("execute BeanNameAware#setBeanName");
.beanName = s;
@Override
(ApplicationContext applicationContext)BeansException
log.info("execute ApplicationContextAware#setApplicationContext");
.applicationContext = applicationContext;
@Override
()Exception
log.info("execute DisposableBean#destroy");
@Override
()Exception
log.info("execute InitializingBean#afterPropertiesSet");
()
log.info("execute User#doInit");
()
log.info("execute User#doDestroy");
定义BeanFactoryPostProcessor的实现类
/**
* @author pdai
*/
@Slf4j
@Component
@Override
(ConfigurableListableBeanFactory configurableListableBeanFactory)BeansException
log.info("execute BeanFactoryPostProcessor#postProcessBeanFactory");
定义InstantiationAwareBeanPostProcessor的实现类
/**
* @author pdai
*/
@Slf4j
@Component
@Override
Object (Class< ?> beanClass, String beanName)BeansException
log.info("execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation for ", beanName);
InstantiationAwareBeanPostProcessor..postProcessBeforeInstantiation(beanClass, beanName);
@Override
(Object bean, String beanName)BeansException
log.info("execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation for ", beanName);
InstantiationAwareBeanPostProcessor..postProcessAfterInstantiation(bean, beanName);
@Override
PropertyValues (PropertyValues pvs, Object bean, String beanName)BeansException
log.info("execute InstantiationAwareBeanPostProcessor#postProcessProperties for ", beanName);
InstantiationAwareBeanPostProcessor..postProcessProperties(pvs, bean, beanName);
定义BeanPostProcessor的实现类
/**
* @author pdai
*/
@Slf4j
@Component
@Override
Object (Object bean, String beanName)BeansException
log.info("execute BeanPostProcessor#postProcessBeforeInitialization for ", beanName);
BeanPostProcessor..postProcessBeforeInitialization(bean, beanName);
@Override
Object (Object bean, String beanName)BeansException
log.info("execute BeanPostProcessor#postProcessAfterInitialization for ", beanName);
BeanPostProcessor..postProcessAfterInitialization(bean, beanName);
通过java配置方式初始化Bean
/**
* @author pdai
*/
@Configuration
@Bean(name = "user", initMethod = "doInit", destroyMethod = "doDestroy")
User ()
User user =User();
user.setName("pdai");
user.setAge(18);
user;
测试的主方法
/**
* Cglib proxy demo.
*
* @author pdai
*/
@Slf4j
/**
* main interface.
*
* @param args args
*/
(String[] args)
log.info("Init application context");
// create and configure beans
AnnotationConfigApplicationContext context =AnnotationConfigApplicationContext(
"tech.pdai.springframework");
// retrieve configured instance
User user = (User) context.getBean("user");
// print info from beans
log.info(user.toString());
log.info("Shutdown application context");
context.registerShutdownHook();
输出结果(剔除无关输出):
12:44:42.547 [main] INFO tech.pdai.springframework.App - Init application context
...
12:44:43.134 [main] INFO tech.pdai.springframework.processor.MyBeanFactoryPostProcessor - execute BeanFactoryPostProcessor#postProcessBeanFactory
...
12:44:43.216 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean user
12:44:43.216 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiationuser
12:44:43.236 [main] INFO tech.pdai.springframework.entity.User - execute User# User()
12:44:43.237 [main] INFO tech.pdai.springframework.entity.User - execute User#setName(pdai)
12:44:43.237 [main] INFO tech.pdai.springframework.entity.User - execute User#setAge(18)
12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiationuser
12:44:43.237 [main] INFO tech.pdai.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessPropertiesuser
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanNameAware#setBeanName
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute BeanFactoryAware#setBeanFactory
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute ApplicationContextAware#setApplicationContext
12:44:43.242 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessBeforeInitializationuser
12:44:43.242 [main] INFO tech.pdai.springframework.entity.User - execute InitializingBean#afterPropertiesSet
12:44:43.243 [main] INFO tech.pdai.springframework.entity.User - execute User#doInit
12:44:43.243 [main] INFO tech.pdai.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessAfterInitializationuser
12:44:43.270 [main] INFO tech.pdai.springframework.App - User(name=pdai, age=18)
12:44:43.270 [main] INFO tech.pdai.springframework.App - Shutdown application context
12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute DisposableBean#destroy
12:44:43.276 [SpringContextShutdownHook] INFO tech.pdai.springframework.entity.User - execute User#doDestroy
参考文章??https://juejin.cn/post/6844903843596107790??
??https://www.zhihu.com/question/438247718/answer/1730527725??
更多文章
首先, 从Spring框架的整体架构和组成对整体框架有个认知。
- ?Spring基础 - Spring和Spring框架组成?
- Spring是什么?它是怎么诞生的?有哪些主要的组件和核心功能呢? 本文通过这几个问题帮助你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的核心(IoC和AOP),同时对IoC和AOP进行案例使用分析。
- ?Spring基础 - Spring简单例子引入Spring的核心?
- 上文中我们简单介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文主要承接上文,向你展示Spring Framework组件的典型应用场景和基于这个场景设计出的简单案例,并以此引出Spring的核心要点,比如IOC和AOP等;在此基础上还引入了不同的配置方式, 如XML,Java配置和注解方式的差异。
- ?Spring基础 - Spring核心之控制反转(IOC)?
- 在Spring基础 - Spring简单例子引入Spring的核心中向你展示了IoC的基础含义,同时以此发散了一些IoC相关知识点; 本节将在此基础上进一步解读IOC的含义以及IOC的使用方式
- ?Spring基础 - Spring核心之面向切面编程(AOP)?
- 在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式。
基于Spring框架和IOC,AOP的基础,为构建上层web应用,需要进一步学习SpringMVC。
- ?Spring基础 - SpringMVC请求流程和案例?
- 前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术基础上,遵循上述Web MVC的规范推出的web开发框架,目的是为了简化Java栈的web开发。 本文主要介绍SpringMVC的请求流程和基础案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码分析
- ?Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计?
- 在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解。本文将帮助你站在设计者的角度去看IOC最顶层的结构设计
- ?Spring进阶 - Spring IOC实现原理详解之IOC初始化流程?
- 上文,我们看了IOC设计要点和设计结构;紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
- ?Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)?
- 上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个
ConcurrentHashMap< String, Object>
;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文主要研究的内容?
- ?Spring进阶 - Spring AOP实现原理详解之切面实现?
- 前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理增强实现做准备的过程)。
- ?Spring进阶 - Spring AOP实现原理详解之AOP代理?
- 上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上继续介绍,代理(cglib代理和JDK代理)的实现过程。
- ?Spring进阶 - Spring AOP实现原理详解之Cglib代理实现?
- 我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理。
- ?Spring进阶 - Spring AOP实现原理详解之JDK代理实现?
- 上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分。
- ?Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程?
- 前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
- ?Spring进阶 - SpringMVC实现原理之DispatcherServlet处理请求的过程?
- 前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析。
推荐阅读
- #夏日挑战赛# HarmonyOS - 方舟开发框架ArkUI 流光按钮效果
- Microsoft Intune 部署第三方应用至 Windows 11
- springboot中内置tomcat什么时候创建的,又是什么时候启动的()
- nginx配置 解决 vue history模式下空白 ,以及SSL证书安装
- Java 线程系列Java 天生就是多线程
- Java后端常见面试题总结
- JAVA经典面试题附答案(持续更新版)
- 小程序输入框完成自动切换到下个输入框
- vue - ES6模块化promisewebpack打包(所在在学的朋友们先看这篇,看了不吃亏)...