手写 Spring 13 - 改造代理对象的创建过程及代理对象的属性填充
# 解析
改造 bean 的创建过程,将代理对象的创建由原先的 bean 实例化之前创建,改为 bean 实例化之后,在 BeanPostProcessor 的初始化后置处理实现。
# 改造代理对象的创建过程
原先 aop 代理对象的创建是在 bean 实例化之前(DefaultAdvisorAutoProxyCreator#postProcessBeforeInstantiation())创建的,现在改为在 BeanPostProcessor 的初始化后置处理实现(DefaultAdvisorAutoProxyCreator#postProcessAfterInitialization())。
在创建代理对象时,又由于最终会调用 TargetSource#getTargetClass() 获取接口,所以改造为判断是 cglib 还是 jdk 的代理接口按需返回。
# 定义一些职责和能力
- 无
# 具体的实现
- DefaultAdvisorAutoProxyCreator 改造
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
private DefaultListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = (DefaultListableBeanFactory) beanFactory;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) {
return pvs;
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
private boolean isInfrastructureClass(Class<?> beanClass) {
return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (isInfrastructureClass(bean.getClass())) {
return null;
}
Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
// 不匹配当前类,过滤
ClassFilter classFilter = advisor.getPointcut().getClassFilter();
if (classFilter != null && !classFilter.matches(bean.getClass())) {
continue;
}
// 转换为代理对象返回
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTargetSource(new TargetSource(bean));
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
advisedSupport.setProxyTargetClass(false); // 默认使用 cglib 代理
return new ProxyFactory(advisedSupport).getProxy();
}
return null;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
- TargetSource 改造
public class TargetSource {
private final Object target;
public TargetSource(Object target) {
this.target = target;
}
public Class<?>[] getTargetClass() {
Class<?> clazz = this.target.getClass();
clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
return clazz.getInterfaces();
}
public Object getTarget() {
return target;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 将实现加入原有的逻辑中
- AbstractAutowireCapableBeanFactory 创建 bean 流程改造
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
// 判断是否返回 代理 Bean 对象(注释原因,改用 BeanPostProcessor#postProcessAfterInitialization() 实现)
// bean = resolveBeforeInstantiation(beanName, beanDefinition);
// if (bean != null) {
// return bean;
// }
// 实例化
bean = createBeanInstance(beanName, beanDefinition, args);
// 省略...
} catch (Exception e) {
throw new BeansException("Failed to bean:[" + beanName + "] instance", e);
}
// 添加单例 Bean 缓存
if (beanDefinition.isSingleton()) {
// 注册实现了 DisposableBean 接口的 单例Bean 对象,留待容器停止的时候调用。
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingleton(beanName, bean);
}
return bean;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 测试
- 配置文件,延用之前章节的 spring-advice.xml。
<?xml version="1.0" encoding="utf-8" ?>
<beans>
<!-- 目标类 -->
<bean id="tiger" class="com.snail.springframework.beans.factory.bean.Tiger">
<property name="name" value="name-xml-init-wow!"></property>
</bean>
<bean class="com.snail.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!-- 切面逻辑 -->
<bean id="tigerAdvice" class="com.snail.springframework.aop.aspectj.TigerAdvice"/>
<bean id="methodInterceptor" class="com.snail.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor">
<property name="methodBeforeAdvice" ref="tigerAdvice"/>
</bean>
<!-- 切入点 -->
<bean class="com.snail.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="advice" ref="methodInterceptor"></property>
<!-- cglib 代理 -->
<property name="expression" value="execution(* com.snail.springframework.beans.factory.bean.Animal.*(..))"></property>
</bean>
</beans>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 测试类,延用之前章节的 AspectJAopTest#aopSpringAdviceTest()。
public class AspectJAopTest {
/**
* aop 和 spring 整合测试
*/
@Test
public void aopSpringAdviceTest() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-advice.xml");
Animal proxy = (Animal) context.getBean("tiger");
// System.out.println("------------------" + DateUtil.now());
// proxy.setName("wow^^ hu~ Proxy");
System.out.println("------------------" + DateUtil.now());
// debug 查看是是否代理类:Tiger$$EnhancerByCGLIB$$ced6ff89@1860
System.out.println("proxy tiger name:" + proxy.getAnimalName());
System.out.println("------------------" + DateUtil.now());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 测试结果
------------------2023-09-18 18:36:32
TigerAdvice method before() -> method:getAnimalName(), args:null
TigerAdvice method before() -> 前置aop, 进行一些操作, sleep(2000)
proxy tiger name:name-xml-init-wow!
------------------2023-09-18 18:36:34
2
3
4
5
# 代理对象的属性填充
在我们实现的 Spring 中,bean 默认使用 cglib 来实例化的。
cglib 通常用于在运行时生成Java类的子类。cglib 生成的子类会继承父类的私有属性和方法,但不会自动继承属性的值。属性值的初始化需要在子类中进行处理。
而我们上章节已经在 bean 使用 cglib 实例化后,属性填充之前,利用 BeanPostProcessor 来修改属性值(解析@Value @Autowired等)。
而现在将 代理对象 的创建,放在了 bean 实例化后,属性填充之后,初始化扩展的 BeanPostProcessor#postProcessAfterInitialization(),所以属性已经做了填充,代码无需改动。
# 定义一些职责和能力
- 无
# 具体的实现
- 无
# 将实现加入原有的逻辑中
- 无
# 测试
xml 准备,无。
提前准备,无。
测试类,如上
AspectJAopTest#aopSpringAdviceTest()
。测试结果,无。
# 总结
需要对 Spring 生命周期了解,及什么时候可以做哪些事情。
Spring 框架中的 Bean 的生命周期包括以下阶段:
- 实例化(Instantiation):在这个阶段,Spring 容器根据 Bean 定义创建一个 Bean 的实例。这可以通过构造函数实例化、工厂方法或其他方式来完成。
- 属性赋值(Populate Properties):在 Bean 实例化后,Spring 容器会将配置的属性值和依赖注入到 Bean 中。这可以通过 XML 配置、Java 注解或 Java 配置来完成。
- Bean 初始化前(Initialization Before):在这个阶段,Spring 容器会调用 Bean 的初始化方法(如果有的话)。你可以自定义初始化方法,例如使用
@PostConstruct
注解。 - Bean 初始化(Initialization):在这个阶段,Spring 容器会调用 Bean 的初始化方法。这是 Bean 实际准备就绪的时候。
- Bean 初始化后(Initialization After):在这个阶段,Spring 容器会执行 Bean 初始化后的一些定制操作。你可以使用
BeanPostProcessor
接口来自定义这些操作。 - Bean 可用(Bean Ready):在上述阶段完成后,Bean 实例已经可以供应用程序使用了。
- 销毁前(Destruction Before):在 Bean 销毁之前,Spring 容器会调用 Bean 的销毁前方法(如果有的话)。你可以自定义销毁前方法,例如使用
@PreDestroy
注解。 - 销毁(Destruction):在这个阶段,Spring 容器会销毁 Bean 实例,释放资源。
- 销毁后(Destruction After):在 Bean 销毁后,Spring 容器会执行一些额外的清理操作。
可以通过配置和自定义方法来干预和控制 Bean 的生命周期中的各个阶段。
打赏一下
「真诚赞赏,手留余香」
# 打赏记录
打赏者 | 打助金额 (元) | 支付方式 | 时间 | 备注 |
---|---|---|---|---|
John | 12 | 微信 | 2020-06-09 | tip of you |
艾斯 | 32 | 支付宝 | 2020-07-11 | 火拳赞赏 |
HickSalmon | 15 | 微信 | 2020-09-21 | 有赏交流 |