Spring源码解析:第12节深入探讨Spring Bean创建的第三阶段

2026-05-06 06:401阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

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

Spring源码解析:第12节深入探讨Spring Bean创建的第三阶段

继续上一篇关于Spring Bean创建过程的解读,上一篇介绍了Spring在创建过程中使用的`doGetBean`方法。在执行过程中,会调用`getSingleton`方法,并设置一个lambda表达式。这个lambda表达式是`ObjectFac`的实例。

具体来说,`getSingleton`方法用于获取单例Bean。在Spring中,单例Bean的创建通常遵循以下步骤:

1. Bean定义:在Spring配置文件或注解中定义Bean,指定其类名或工厂方法。

2.Bean创建:Spring容器启动时,会根据配置创建Bean实例。

3.单例缓存:Spring容器会维护一个单例池,用于存储单例Bean的引用。

4.获取Bean:当请求某个Bean时,Spring会从单例池中获取该Bean的引用,如果不存在,则创建一个新的实例并放入池中。

在`doGetBean`方法中,Spring会检查单例池中是否已经存在目标Bean的实例。如果不存在,会调用`getSingleton`方法创建新的实例。`getSingleton`方法接受一个lambda表达式作为参数,这个lambda表达式负责创建新的Bean实例。

以下是一个简化版的lambda表达式示例:

java

ObjectFac objectFac=() -> new YourBeanImplementation();

这里的`YourBeanImplementation`是你要创建的Bean的实现类。这个lambda表达式会在单例池中创建一个新的`YourBeanImplementation`实例。

总结一下,Spring在处理Bean创建和获取时,会利用单例模式确保每个Bean只创建一次,并通过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时放进去的。

看源码:

Spring源码解析:第12节深入探讨Spring Bean创建的第三阶段

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对象。

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

Spring源码解析:第12节深入探讨Spring Bean创建的第三阶段

继续上一篇关于Spring Bean创建过程的解读,上一篇介绍了Spring在创建过程中使用的`doGetBean`方法。在执行过程中,会调用`getSingleton`方法,并设置一个lambda表达式。这个lambda表达式是`ObjectFac`的实例。

具体来说,`getSingleton`方法用于获取单例Bean。在Spring中,单例Bean的创建通常遵循以下步骤:

1. Bean定义:在Spring配置文件或注解中定义Bean,指定其类名或工厂方法。

2.Bean创建:Spring容器启动时,会根据配置创建Bean实例。

3.单例缓存:Spring容器会维护一个单例池,用于存储单例Bean的引用。

4.获取Bean:当请求某个Bean时,Spring会从单例池中获取该Bean的引用,如果不存在,则创建一个新的实例并放入池中。

在`doGetBean`方法中,Spring会检查单例池中是否已经存在目标Bean的实例。如果不存在,会调用`getSingleton`方法创建新的实例。`getSingleton`方法接受一个lambda表达式作为参数,这个lambda表达式负责创建新的Bean实例。

以下是一个简化版的lambda表达式示例:

java

ObjectFac objectFac=() -> new YourBeanImplementation();

这里的`YourBeanImplementation`是你要创建的Bean的实现类。这个lambda表达式会在单例池中创建一个新的`YourBeanImplementation`实例。

总结一下,Spring在处理Bean创建和获取时,会利用单例模式确保每个Bean只创建一次,并通过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时放进去的。

看源码:

Spring源码解析:第12节深入探讨Spring Bean创建的第三阶段

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对象。