您的位置:首页 > 编程语言 > Java开发

Spring 源码(12)Spring Bean 的创建过程(3)

2022-05-11 13:50 726 查看

继续上一篇

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

Spring
Bean
的创建分为实例化+初始化,当然还有属性填充,这里进行提前实例化其实就是给了一个扩展点,让对象可以提前创建,而不用再继续走
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="https://www.cnblogs.com/redwinter/">redwinter</a>
* @since 1.0
**/
public class MyBeforeInstantiation {

public void beforeInvoke(){
System.out.println("提前实例化,开始执行业务....");
}
}

创建一个

InstantiationAwareBeanPostProcessor
的实现类:

/**
* @author <a href="https://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="https://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="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://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="https://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
对象。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: