Spring源码-生命周期-createBean的整个流程
具体的步骤:
createBean从哪里进来的!!!
1.CreatBean的入口,这里先描述逻辑,逻辑后是代码
这些都是
1.看单例池中是否存在:
判断是不是FactoryBean
2.单例池不存在:
2.1当前BeanFactory中是否存在beanName对象的BeanDefinition,不存在从ParentBeanFactory中去获取
返回父类中的getBean()
存在对象的beanDefinition:
2.2创建Bean
2.2.1得到合并后的BeanDefinition,因为存在下面的情况,不明白的可以去看Spring的生命周期【上】
<bean id="parent" scope="prototype" abstract="true"></bean>
<bean id="userService" class="com.luban.service.UserService" parent="parent"></bean>
2.2.2加载DependsOn的bean
2.2.2.1 判断beanName是不是也被dep依赖了,如果是,就是相互依赖
2.2.2.2 存在在两个map中,先创建依赖的哪个bean
2.2.3 根据Scope去创建bean
2.2.3.1 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
单例bean可能是一个FactoryBean,所以需要单独再去factoryBeanObjectCache中去获取对 应的对象
2.2.3.2如果是原型的话,就是直接去创建一个对象,不把这个对象加入到单例池中
去判断是不是FactoryBean,是的话,就调用他的getObject方法
2.2.3.3如果是request的情况下,就把对象放入到request.getAttribute当中去,因为getAttribute是一 个map
如果是session的情况下,就把对象放入到Session.getAttribute当中去,因为getAttribute是 一个map
if的逻辑:
else的逻辑:
在else中是去获取ParentBeanFactory,如果ParentBeanFactory存在并且子类的BeanDefinition也不存在这个bd,就会去父类中去getBean条件:if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
如果父类中不存在,我们就会去创建Bean
首先从MergedLocalBeanDefinition获取到RootBeanDefinition,然后
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.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 当前BeanFactory中不存beanName对象的BeanDefinition,那么则从ParentBeanFactory中去获取
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);
}
}
// 创建Bean
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 得到合并后的BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 加载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 + "'");
}
// 存在在两个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);
}
}
}
// 根据Scope去创建bean
// Create bean instance.
if (mbd.isSingleton()) {
// 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
sharedInstance = getSingleton(beanName, () -> {
try {
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;
}
});
// 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);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}//去判断是不是FactoryBean,是的话,就调用他的getObject方法
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope(); // request, session
final 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 {//如果是request的情况下,就把对象放入到request.getAttribute当中去,因为getAttribute是一个map
//如果是session的情况下,就把对象放入到Session.getAttribute当中去,因为getAttribute是一个map
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;
}
}
我们进行CreateBean的逻辑:
//我们在创建createBean的时候,会传过来beanName和RootBeanDefinition
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
//我们都知道BeanDefintion是在扫描的时候创建的,但是RootBeanDefition中存在一个beanClass属性
@Nullable
private volatile Object beanClass; // String Class
//为什么是Object类型呢,我们知道扫描,形成BeanDefinition的时候,spring采用的是ASM的方法,并不会把文件加载到内存形成Class,而是直接加载字节码,所以我们beanClass,有的时候是Object,可以存储Class类型,或者是"com.luban.userService"全限定类名的String类型
CeateBean:加载类的逻辑
步骤:
加载类
实例化
填充属性
Aware
初始化
1.加载类的逻辑
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);
}
//点击进入Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
//传进去bd,beanName得出一个Class
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
// 直接返回beanClass
if (mbd.hasBeanClass()) {//判断是不是Class类型,如果是直接设置
return mbd.getBeanClass();
}
else {
//如果是String类型的全限定类名,就加载这个类,形成Class类
// 加载BeanDefinition中beanClass中所指定的类名对应的类
return doResolveBeanClass(mbd, typesToMatch);
}
}
}
在doResolveBeanClass的方法中,我们可以
// 获取BeanDefinition中所指定的beanClass属性的值,beanClass属性的类型为Object,可以指定为某个类名
// className可以有SpEL,所以需要解析
//最后调用return ClassUtils.forName(className, dynamicLoader);
//在Classutils中去判断全限定类名的情况。
那么我们在进行类加载的时候,使用的是什么类加载器呢?
优先级:
1.如果你beanFactory,set的时候,就不会进入到getDefaultClassLoader()这个方法里面来
2.如果你Thread,set的时候,就采取你线程set的
3.如果都没有,就采用加载你这个类的Classloader,如果加载你这类的Classloder是BootStrap
就设置为App
//1.在doResolveBeanClass中有这一行代码
ClassLoader beanClassLoader = getBeanClassLoader();//获取到类加载器
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
public static ClassLoader getDefaultClassLoader() {
// 先取当前线程对应的classloader
// 再取ClassUtils类的classloader
// 最后去系统指定的classloader
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader(); // APpClassLoader
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = ClassUtils.class.getClassLoader();
if (cl == null) { // Bootstrap为null,你的项目
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
cl = ClassLoader.getSystemClassLoader(); // app
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
//两种指定bean的ClassLoader
applicationContext.getBeanFactory().setBeanClassLoader();
//线程的设置
Thread.currentThread().setClassLoader()
2.大概的步骤
在这里插入代码片我们加载完类之后,就是去实例化,然后去填充属性,执行Aware,再初始化的过程中
我们还存在初始化前和初始化后,这主要是为了干预初始化方法
初始化前和初始化后都存在两个钩子:BeanPostProcessor。同时这个BeanPostProcessor就有两个实现方法,这两个方法会在每个bean初始化的时候执行的。
@Component("orderService")
public class OrderService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化中....");
}
}
初始化前:appConfig
初始化后
初始化前:lubanFactoryBean
初始化后
初始化前:orderService
初始化中....
初始化后
初始化前:userService
初始化后
com.luban.service.OrderService@3b22cdd0
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(applicationContext.getBean("orderService"));
}
3.初始化前
里面就存在我们自定义的LubanBeanProcessor。
4.初始化
@Component
public class UserService {
@PostConstruct
public void test1(){
System.out.println("构造,,,,");
}
@PreDestroy
public void test2(){
System.out.println("销毁.....");
}
}
@PostConstruct和PreDestory的逻辑再哪里处理的呢?
在InitDestroyAnnotationBeanPostProcessor,这也是一个BeanPostProcessor
里面也有Before,After
在这个方法里面就是判断是否PostConstruct和PreDestory注解,有的方法都加入到集合中
在上述红箭头指向的两个方法如下:
在InitDestroyAnnotationBeanPostProcessor中调用了 metadata.invokeDestroyMethods(bean, beanName);这些方法就是从集合中拿出带有PostConstruct和PreDestory的注解的方法,然后执行
出现的一个现象:
@Component("orderService")
public class OrderService implements InitializingBean {
@PostConstruct
public void test1(){
System.out.println("构造,,,,");
}
@PreDestroy
public void test2(){
System.out.println("销毁.....");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化中....");
}
}
@Component
public class LubanBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean=="orderService"){
System.out.println("初始化前:"+beanName);
}
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化后");
return null;
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(applicationContext.getBean("orderService"));
}
}
初始化前:appConfig
初始化后
初始化前:lubanFactoryBean
初始化后
初始化前:orderService
初始化中....
初始化后
初始化前:userService
初始化后
com.luban.service.OrderService@48cf768c
Process finished with exit code 0
问题:为什么我添加了@PostConstruct和@PreDestroy没执行呢?
我们去把LubanBeanPostProcessor的return 不为null就可以了,
构造,,,,
初始化中....
构造,,,,
com.luban.service.OrderService@e2d56bf
那原理又体现在那儿呢?
所以当我们获得current的时候,current==null的时候,就直接返回了,不会执行CommonAnnotationBeanPostProcessor了,就不会输出.
这就是牵扯到BeanPostProcessor的一个执行顺序的问题
5.初始化后:AOP的应用
等到AOP的时候再讲
是不是只在初始化的时候去扩展点呢,其实再实例化的时候也存在。
6.实例化前
加载类
实例化前—InstantiationAwareBeanPostProcessor
实例化
实例化后—InstantiationAwareBeanPostProcessor
填充属性
填充属性后—InstantiationAwareBeanPostProcessor
Aware
初始化前—BeanPostProcessor
初始化
初始化后—BeanPostProcessor
@Component
public class LubanBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("实例化前"+beanName);
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("实例化后"+beanName);
}
return true;//true是时候,填充属性才可以执行
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("填充属性后"+beanName);
}
return null;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("初始化前"+beanName);
}
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("初始化后"+beanName);
}
return null;
}
}
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
InstantiationAwareBeanPostProcessor的功能更强大一点,继承了BeanPostProcessor,就存在初始化前和初始化后的方法,再加上实例化前,实例化后,属性填充后的方法
源码分析:
验证:
@Component
public class LubanBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("实例化前"+beanName);
}
return new User();
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("orderService")){
System.out.println("初始化后"+beanName);
}
return null;
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(applicationContext.getBean("orderService"));
}
}
实例化前orderService
初始化后orderService
com.luban.entity.User@200a570f
如果实例化前返回的为null,那么就使用spring自带的创建bean的方法:
进入doCreateBean:
7.实例化后
8.属性填充
下一篇博客写Spring的依赖注入会讲到
9.在实例化和实例化后还存在着一个过程来设置BeanDefinition