第四章 Spring AOP源码分析笔记

本文详细分析了Spring AOP的配置使用,包括AOP入口类的启用、代理类的创建以及如何判断是否生成代理。通过跟踪代码,解释了如何在bean实例化后生成代理对象,并探讨了寻找切面、创建代理以及Aop链式调用的过程,为理解Spring AOP的工作原理提供了深入洞察。
摘要由CSDN通过智能技术生成

一、AOP的配置使用

1、AOP入口

通过扫描注解@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)注册了AOP 入口类,具体看看注解里面的@Import(AspectJAutoProxyRegistrar.class)

/*
* TODO 开启注解AOP
*  替代了:<aop:aspectj-autoproxy/>
* */
@Service
@EnableAspectJAutoProxy(proxyTargetClass = false,exposeProxy = true)
public class EnableAspectJAutoProxyBean {
}

org.springframework.context.annotation.EnableAspectJAutoProxy

在这个类中,注册了AOP入口类 AnnotationAwareAspectJAutoProxyCreator

设置了两个属性:

proxyTargetClass = true

1)目标对象实现了接口 – 使用CGLIB代理机制

2)目标对象没有接口(只有实现类) – 使用CGLIB代理机制

proxyTargetClass = false

1)目标对象实现了接口 – 使用JDK动态代理机制(代理所有实现了的接口)

2)目标对象没有接口(只有实现类) – 使用CGLIB代理机制

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   /**
    * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    * to standard Java interface-based proxies. The default is { @code false}.
    */
   boolean proxyTargetClass() default false;
   /**
    * Indicate that the proxy should be exposed by the AOP framework as a { @code ThreadLocal}
    * for retrieval via the { @link org.springframework.aop.framework.AopContext} class.
    * Off by default, i.e. no guarantees that { @code AopContext} access will work.
    * @since 4.3.1
    */
   boolean exposeProxy() default false;
}

exposeProxy

该属性设置代理对象是否需要暴露,说白了就是是否需要把代理对象设置到ThreadLocal中。

AOP的其他入口类的配置是基于xml的形式

例如:

<!--开启注解aop-->
<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="true"/>

或者

<aop:config proxy-target-class="false">
    <!--<aop:pointcut>在此处定义的pointcut是全局的pointcut可以供所有的aspect使用-->
    <!--id:表示这个pointcut的名称,以方便使用-->
    <aop:pointcut id="addpointcut" expression="execution(public * com.chj.service..*.add(..))"/>
    <aop:pointcut id="delpointcut" expression="execution(public * com.chj.service..*.del*(..))"/>
    <aop:pointcut id="myMethods" expression="execution(public * com.chj.service..*.*(..))"/>
    <!--advisor必须在aspect之前,要不然有xml约束报错-->
    <aop:advisor advice-ref="beforeAdviceBean" order="2" pointcut-ref="myMethods"/>
    <aop:aspect id="aspect1" ref="aspectXml1" order="0">
        <!--<aop:declare-parents types-matching="com.zhuguang.jack.service.MyServiceImpl"-->
        <!--implement-interface="com.zhuguang.jack.aop.IntroductionIntf"-->
        <!--delegate-ref="myintroduction"/>-->
        <!--id:表示这个pointcut的名称,以方便使用-->
        <aop:pointcut id="myMethod2" expression="execution(public * com.chj.service..*.*(..))
            and @annotation(org.springframework.web.bind.annotation.RequestMapping)"/>
        <aop:before method="before" pointcut-ref="myMethods"/>
        <aop:after method="after" pointcut-ref="myMethod2"/>
        <!-- 后置通知  returning="returnVal" 定义返回值 必须与类中声明的名称一样-->
        <aop:after-returning method="afterReturning" returning="returnVal"
                             pointcut="execution(public * com.chj.service..*.*(..))"/>
        <!--异常通知 throwing="throwable" 指定异常通知错误信息变量,必须与类中声明的名称一样-->
        <!--<aop:after-throwing method="afterthrowing" throwing="e" pointcut-ref="myMethods"/>-->
        <aop:around method="around" pointcut-ref="myMethod2"/>
    </aop:aspect>
</aop:config>

2、是否生成代理

当一个bean实例化完成后,会判断该bean是否生成代理,AOP的入口如下:

2.1、Aop代理对象生产入口:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

// Initialize the bean instance.
Object exposedObject = bean;
try {
   //ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
   populateBean(beanName, mbd, instanceWrapper);
   //bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
   exposedObject = initializeBean(beanName, exposedObject, mbd);
}

在这个方法里面,具体是:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(String,Object, RootBeanDefinition)

if (mbd == null || !mbd.isSynthetic()) {
   //这个地方可能生出代理实例,是aop的入口
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;

这是一个BeanPostProcessor接口的运用,initializeBean方法我们都知道是一个bean实例化完成后做的操作,而这个代理实例生成也是在bean实例化完成后做的操作,其核心代码如下:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值