ITPub博客

首页 > 数据库 > 数据库开发技术 > Spring ⑨ AOP 何时创建代理对象

Spring ⑨ AOP 何时创建代理对象

原创 数据库开发技术 作者:DevXTalk 时间:2023-02-15 22:18:10 0 删除 编辑

Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

本章会探究 spring 是在什么时候创建的 AOP 代理对象.为了方便读者理解本章内容不会涉及到过多的源码,只是在宏观层面上让读者了解 AOP 代理对象是在什么时候创建的.

认识 AnnotationAwareAspectJAutoProxyCreator

在开始之前先向读者介绍 AnnotationAwareAspectJAutoProxyCreator 它是 BeanPostProcessor 接口的实现, spring 对目标对象进行代理就是以它作为入口. 本章不会对该类进行详细讲解,只是让大家知道这个类跟 spring 的 AOP 功能十分密切。它将 AOP 技术与 bean 创建过程结合起来.

场景

public class AopExp1 {

public static void main(String[] args) throws Exception {

LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = loggerContext.getLogger(AnnotationAwareAspectJAutoProxyCreator.class);
logger.setLevel(Level.TRACE);

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

AnnotationAwareAspectJAutoProxyCreator proxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
proxyCreator.setBeanFactory(factory);
factory.addBeanPostProcessor(proxyCreator);

factory.registerBeanDefinition("myAspect" , BeanDefinitionBuilder
.genericBeanDefinition(MyAspect.class)
.getBeanDefinition());

factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
.genericBeanDefinition(Bean1.class)
.getBeanDefinition());

Bean1 bean1 = factory.getBean(Bean1.class);
System.out.println("bean1 type -> " + bean1.getClass());
bean1.foo();
}


@Aspect
static class MyAspect {

@Before("execution(* foo())")
public void before() {
System.out.println("@Aspect @Before ------------------------------");
}

}

static class Bean1 {


public Bean1() {
System.out.println("======================== bean1 实例化 ");
}

public void foo() {
System.out.println("======================== Bean1 foo ");
}
}
}
运行日志输出:

观察日志输出,在 Creating shared instance of singleton bean 后输出了 Found AspectJ method , 之后调用了 bean1 的无参数构造函数实例化了 bean1 。在这之后输出了 Creating implicit proxy for bean 'bean1' 说明这时候为 bean1 创建了代理对象。接下来就来探究这些步骤是在什么地方什么时候发生的。

21:03:53.969 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
21:03:54.045 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void org.devx.spring.certified.professional.edu.hp.experiment.AopExp1$MyAspect.before()
======================== bean1 实例化
21:03:54.168 [main] TRACE org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator - Creating implicit proxy for bean 'bean1' with 0 common interceptors and 2 specific interceptors
bean1 type -> class org.devx.spring.certified.professional.edu.hp.experiment.AopExp1$Bean1$$EnhancerBySpringCGLIB$$5974b8b5
21:03:54.274 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myAspect'
@Aspect @Before ------------------------------
======================== Bean1 foo

在 bean 的创建过程中首先会经过 resolveBeforeInstantiation 该方法中会去调用 BeanPostProcessor 的 postProcessBeforeInstantiation 方法, 此时目标对象还没有被创建。

为了排除干扰我们这里只添加了 AnnotationAwareAspectJAutoProxyCreator 这一个 BeanPostProcessor.

AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation

在这个方法中会去探测 AspectJ 切面类和 Advisor 实现类 ,并将 AspectJ 切面类封装为 Advisor. 也就是我们在日志输出中看到的 Found AspectJ method 这一步。注意这里并没有去创建代理对象,除非有自定义的 TargetSource 实现。

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);

if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}

// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

return null;
}
AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization

在这里 bean 已经经过了完整的初始化过程, 才会去创建代理对象。它是在 AbstractAutowireCapableBeanFactory#initializeBean 的最后被调用的。

AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

这里也只有 AnnotationAwareAspectJAutoProxyCreator 这一个 BeanPostProcessor.

这里的 wrapIfNecessary 才会真正去创建代理对象。还有一种创建代理对象的场景适用于 循环引用 的场景,在 getEarlyBeanReference 方法中创建了代理对象。详情请看 Spring ⑦ 循环引用问题。

创建 AOP 代理对象的过程大致如下图,之后的章节中会详细探究 spring AOP 创建代理对象的过程。


DevX 会持续分享 Java 技术干货,如果你觉得本文对你有帮助希望你可以分享给更多的朋友看到。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

DevX 不止于技术

原文作者:DevXTalk;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-23

  • 博文量
    178
  • 访问量
    82597