Spring源码第12篇:深入解析Spring Bean创建过程(第3阶段)疑问?

2026-05-25 17:291阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2097个文字,预计阅读时间需要9分钟。

Spring源码第12篇:深入解析Spring Bean创建过程(第3阶段)疑问?

继承上一篇,本文将解读Spring Bean的创建过程。上一篇文章介绍了Spring在创建过程中使用`doGetBean`方法,并在执行过程中调用`getSingleton`方法。此外,还设置了一个lambda表达式,该表达式是`ObjectFac`。

Spring Bean的创建过程大致如下:

1. 实例化BeanFactory:Spring容器启动时,会创建一个或多个`BeanFactory`实例,如`ApplicationContext`或`BeanFactory`。

2. 注册Bean定义:在`BeanFactory`中注册Bean定义,包括Bean的类名、构造函数参数、依赖关系等。

3. 创建Bean实例:当需要使用某个Bean时,Spring会根据Bean定义创建其实例。

Spring源码第12篇:深入解析Spring Bean创建过程(第3阶段)疑问?

4. 依赖注入:Spring会自动注入Bean的依赖关系,包括构造函数注入和属性注入。

5. 初始化Bean:Spring会调用Bean的初始化方法,如`init-method`。

6. 使用Bean:现在Bean已经准备好,可以被应用程序使用了。

在创建Bean的过程中,`doGetBean`方法扮演着重要角色。以下是`doGetBean`方法的大致步骤:

1. 检查缓存:首先检查缓存中是否已经存在该Bean的实例。

2. 创建Bean实例:如果缓存中没有,则根据Bean定义创建一个新的实例。

3. 依赖注入:对Bean实例进行依赖注入。

4. 初始化Bean:调用Bean的初始化方法。

5. 返回Bean实例:将创建好的Bean实例返回给调用者。

在执行过程中,`getSingleton`方法被用来获取单例Bean的实例。如果单例Bean尚未创建,`getSingleton`会创建一个新的实例;如果已经存在,则直接返回现有的实例。

此外,设置了一个lambda表达式,其形式为`ObjectFac`。这个lambda表达式通常用于简化Bean的创建和获取过程。例如,可以这样使用:

javaObjectFac myBean=() -> new MyBeanImplementation();

这里的`ObjectFac`是一个函数式接口,它定义了一个没有参数和返回值的`apply`方法。通过lambda表达式,我们可以直接创建并返回一个Bean实例。

继续上一篇Spring Bean的创建过程的解读,上一篇介绍了Spring在创建过程中doGetBean方法,在执行过程中会调用getSingleton方法并且设置一个lambda表达式,这个lambda表达式是ObjectFactory的实现,当调用这个接口的getObject方法时就会执行到createBean方法,在createBean方法中会进行bean类型的解析,并且会进行方法覆盖的设置,当我们配置了如:lookup-method或者replace-method方法的时候就会在创建Bean的过程中设置一个CGLIB的工厂类为Bean的对象,当调用的时候就会触发CGLIB的拦截器方法执行具体的Bean的获取,如果是单例对象引用了多例对象,那么就会每次创建一个新的对象给调用的方法执行。

接下来继续解读Spring 创建Bean的过程。

早期Bean的创建

createBean方法中有一段代码:

try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 解析提前实例化,使用InstantiationAwareBeanPostProcessor实现 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } }

点进去:

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. // 判断是否有InstantiationAwareBeanPostProcessor在容器中 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; }

这里判断了容器中如果有实现InstantiationAwareBeanPostProcessor接口,那么就执行前置实例化,InstantiationAwareBeanPostProcessor接口继承了BeanPostProcessor,并且这个接口的方法跟BeanPostProcessor非常相似,InstantiationAwareBeanPostProcessor的接口一个是前置的实例化postProcessBeforeInstantiation,一个是后置的实例化postProcessAfterInstantiation,而BeanPostProcessor的接口一个是前置初始化postProcessBeforeInitialization,一个是后置初始化postProcessAfterInitialization

SpringBean的创建分为实例化+初始化,当然还有属性填充,这里进行提前实例化其实就是给了一个扩展点,让对象可以提前创建,而不用再继续走doCreateBean方法里面的复杂逻辑,这样的话就提供给用户能够自己控制对象的创建过程以及执行增强等操作。

那这个实例化增强类是何时放进Spring容器的呢?

答案很简单,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor,那么自然也就是在注册BeanPostProcessor时放进去的。

看源码:

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); // Remove from old position, if any // 先删除掉旧的 this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware // 如果是InstantiationAwareBeanPostProcessor 设置属性 if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } // 设置销毁的标识位 if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // Add to end of list // 添加到链表尾 this.beanPostProcessors.add(beanPostProcessor); }

接下来试试提前实例化的案例:

InstantiationAwareBeanPostProcessor 实验

创建一个需要提前实例化的对象:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyBeforeInstantiation { public void beforeInvoke(){ System.out.println("提前实例化,开始执行业务...."); } }

创建一个InstantiationAwareBeanPostProcessor的实现类:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInstantiation 方法"); // 提前进行实例化 if (beanClass == MyBeforeInstantiation.class) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(beanClass); enhancer.setCallback(new MyMethodInterceptor()); Object obj = enhancer.create(); System.out.println("创建对象:" + obj); return obj; } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessAfterInstantiation 方法"); return false; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessProperties 方法"); return pvs; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInitialization 方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessAfterInitialization 方法"); return bean; } }

这里使用了CGLIB 动态代理去增强创建代理对象,编写一个回调拦截器:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("方法执行前:"+method); Object o1 = methodProxy.invokeSuper(o, objects); System.out.println("方法执行后:"+method); return o1; } }

xml配置:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="myBeforeInstantiation" class="com.redwinter.test.beforeInstantiation.MyBeforeInstantiation"/> <bean id="myInstantiationAwareBeanPostProcessor" class="com.redwinter.test.beforeInstantiation.MyInstantiationAwareBeanPostProcessor"/> </beans>

测试类:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class BeforeInstantiationTest { @Test public void test(){ ApplicationContext ac = new ClassPathXmlApplicationContext("before-instantiation.xml"); MyBeforeInstantiation bean = ac.getBean(MyBeforeInstantiation.class); bean.beforeInvoke(); } }

输出:

beanName: myBeforeInstantiation执行了 postProcessBeforeInstantiation 方法 方法执行前:public java.lang.String java.lang.Object.toString() 方法执行前:public native int java.lang.Object.hashCode() 方法执行后:public native int java.lang.Object.hashCode() 方法执行后:public java.lang.String java.lang.Object.toString() 创建对象:com.redwinter.test.beforeInstantiation.MyBeforeInstantiation$$EnhancerByCGLIB$$f92db8b4@1fd3711 beanName: myBeforeInstantiation执行了 postProcessAfterInitialization 方法 方法执行前:public void com.redwinter.test.beforeInstantiation.MyBeforeInstantiation.beforeInvoke() 提前实例化,开始执行业务.... 方法执行后:public void com.redwinter.test.beforeInstantiation.MyBeforeInstantiation.beforeInvoke()

可以看到,这里只执行了两个方法,一个是postProcessBeforeInstantiation,是InstantiationAwareBeanPostProcessor的前置实例化接口,一个是postProcessAfterInitialization,是BeanPostProcessor的后置实例化接口。

相当于说Bean对象提前被创建了,而没有执行下面的doCreateBean方法的逻辑。 Spring设计了很多的扩展点,帮助用户实现很多自定义的处理,Spring强大之处就在这里。

这篇就介绍到这里,下一篇介绍Spring其他方式的进行提前创建Bean对象。

本文共计2097个文字,预计阅读时间需要9分钟。

Spring源码第12篇:深入解析Spring Bean创建过程(第3阶段)疑问?

继承上一篇,本文将解读Spring Bean的创建过程。上一篇文章介绍了Spring在创建过程中使用`doGetBean`方法,并在执行过程中调用`getSingleton`方法。此外,还设置了一个lambda表达式,该表达式是`ObjectFac`。

Spring Bean的创建过程大致如下:

1. 实例化BeanFactory:Spring容器启动时,会创建一个或多个`BeanFactory`实例,如`ApplicationContext`或`BeanFactory`。

2. 注册Bean定义:在`BeanFactory`中注册Bean定义,包括Bean的类名、构造函数参数、依赖关系等。

3. 创建Bean实例:当需要使用某个Bean时,Spring会根据Bean定义创建其实例。

Spring源码第12篇:深入解析Spring Bean创建过程(第3阶段)疑问?

4. 依赖注入:Spring会自动注入Bean的依赖关系,包括构造函数注入和属性注入。

5. 初始化Bean:Spring会调用Bean的初始化方法,如`init-method`。

6. 使用Bean:现在Bean已经准备好,可以被应用程序使用了。

在创建Bean的过程中,`doGetBean`方法扮演着重要角色。以下是`doGetBean`方法的大致步骤:

1. 检查缓存:首先检查缓存中是否已经存在该Bean的实例。

2. 创建Bean实例:如果缓存中没有,则根据Bean定义创建一个新的实例。

3. 依赖注入:对Bean实例进行依赖注入。

4. 初始化Bean:调用Bean的初始化方法。

5. 返回Bean实例:将创建好的Bean实例返回给调用者。

在执行过程中,`getSingleton`方法被用来获取单例Bean的实例。如果单例Bean尚未创建,`getSingleton`会创建一个新的实例;如果已经存在,则直接返回现有的实例。

此外,设置了一个lambda表达式,其形式为`ObjectFac`。这个lambda表达式通常用于简化Bean的创建和获取过程。例如,可以这样使用:

javaObjectFac myBean=() -> new MyBeanImplementation();

这里的`ObjectFac`是一个函数式接口,它定义了一个没有参数和返回值的`apply`方法。通过lambda表达式,我们可以直接创建并返回一个Bean实例。

继续上一篇Spring Bean的创建过程的解读,上一篇介绍了Spring在创建过程中doGetBean方法,在执行过程中会调用getSingleton方法并且设置一个lambda表达式,这个lambda表达式是ObjectFactory的实现,当调用这个接口的getObject方法时就会执行到createBean方法,在createBean方法中会进行bean类型的解析,并且会进行方法覆盖的设置,当我们配置了如:lookup-method或者replace-method方法的时候就会在创建Bean的过程中设置一个CGLIB的工厂类为Bean的对象,当调用的时候就会触发CGLIB的拦截器方法执行具体的Bean的获取,如果是单例对象引用了多例对象,那么就会每次创建一个新的对象给调用的方法执行。

接下来继续解读Spring 创建Bean的过程。

早期Bean的创建

createBean方法中有一段代码:

try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 解析提前实例化,使用InstantiationAwareBeanPostProcessor实现 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } }

点进去:

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. // 判断是否有InstantiationAwareBeanPostProcessor在容器中 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; }

这里判断了容器中如果有实现InstantiationAwareBeanPostProcessor接口,那么就执行前置实例化,InstantiationAwareBeanPostProcessor接口继承了BeanPostProcessor,并且这个接口的方法跟BeanPostProcessor非常相似,InstantiationAwareBeanPostProcessor的接口一个是前置的实例化postProcessBeforeInstantiation,一个是后置的实例化postProcessAfterInstantiation,而BeanPostProcessor的接口一个是前置初始化postProcessBeforeInitialization,一个是后置初始化postProcessAfterInitialization

SpringBean的创建分为实例化+初始化,当然还有属性填充,这里进行提前实例化其实就是给了一个扩展点,让对象可以提前创建,而不用再继续走doCreateBean方法里面的复杂逻辑,这样的话就提供给用户能够自己控制对象的创建过程以及执行增强等操作。

那这个实例化增强类是何时放进Spring容器的呢?

答案很简单,InstantiationAwareBeanPostProcessor是一个BeanPostProcessor,那么自然也就是在注册BeanPostProcessor时放进去的。

看源码:

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); // Remove from old position, if any // 先删除掉旧的 this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware // 如果是InstantiationAwareBeanPostProcessor 设置属性 if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } // 设置销毁的标识位 if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // Add to end of list // 添加到链表尾 this.beanPostProcessors.add(beanPostProcessor); }

接下来试试提前实例化的案例:

InstantiationAwareBeanPostProcessor 实验

创建一个需要提前实例化的对象:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyBeforeInstantiation { public void beforeInvoke(){ System.out.println("提前实例化,开始执行业务...."); } }

创建一个InstantiationAwareBeanPostProcessor的实现类:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInstantiation 方法"); // 提前进行实例化 if (beanClass == MyBeforeInstantiation.class) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(beanClass); enhancer.setCallback(new MyMethodInterceptor()); Object obj = enhancer.create(); System.out.println("创建对象:" + obj); return obj; } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessAfterInstantiation 方法"); return false; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessProperties 方法"); return pvs; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInitialization 方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("beanName: " + beanName + "执行了 postProcessAfterInitialization 方法"); return bean; } }

这里使用了CGLIB 动态代理去增强创建代理对象,编写一个回调拦截器:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("方法执行前:"+method); Object o1 = methodProxy.invokeSuper(o, objects); System.out.println("方法执行后:"+method); return o1; } }

xml配置:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="myBeforeInstantiation" class="com.redwinter.test.beforeInstantiation.MyBeforeInstantiation"/> <bean id="myInstantiationAwareBeanPostProcessor" class="com.redwinter.test.beforeInstantiation.MyInstantiationAwareBeanPostProcessor"/> </beans>

测试类:

/** * @author <a href="www.cnblogs.com/redwinter/">redwinter</a> * @since 1.0 **/ public class BeforeInstantiationTest { @Test public void test(){ ApplicationContext ac = new ClassPathXmlApplicationContext("before-instantiation.xml"); MyBeforeInstantiation bean = ac.getBean(MyBeforeInstantiation.class); bean.beforeInvoke(); } }

输出:

beanName: myBeforeInstantiation执行了 postProcessBeforeInstantiation 方法 方法执行前:public java.lang.String java.lang.Object.toString() 方法执行前:public native int java.lang.Object.hashCode() 方法执行后:public native int java.lang.Object.hashCode() 方法执行后:public java.lang.String java.lang.Object.toString() 创建对象:com.redwinter.test.beforeInstantiation.MyBeforeInstantiation$$EnhancerByCGLIB$$f92db8b4@1fd3711 beanName: myBeforeInstantiation执行了 postProcessAfterInitialization 方法 方法执行前:public void com.redwinter.test.beforeInstantiation.MyBeforeInstantiation.beforeInvoke() 提前实例化,开始执行业务.... 方法执行后:public void com.redwinter.test.beforeInstantiation.MyBeforeInstantiation.beforeInvoke()

可以看到,这里只执行了两个方法,一个是postProcessBeforeInstantiation,是InstantiationAwareBeanPostProcessor的前置实例化接口,一个是postProcessAfterInitialization,是BeanPostProcessor的后置实例化接口。

相当于说Bean对象提前被创建了,而没有执行下面的doCreateBean方法的逻辑。 Spring设计了很多的扩展点,帮助用户实现很多自定义的处理,Spring强大之处就在这里。

这篇就介绍到这里,下一篇介绍Spring其他方式的进行提前创建Bean对象。