@(工作笔记)

spring-aop-record

Alt text

[TOC]


  • Springboot apo 怎么工作的?

@SpringBootApplication -> @EnableAutoConfiguration -> @Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector.class->process方法 ->根据pom里的文件 使用 getAutoConfigurationEntry() 筛选

每个spring-boot-starter包里面都有一个 autoconfigure包, 这个包里面有 META-INF/spring.factories 文件, 这是配置文件

里面有 配置类的权限定类名, 这个类是配置类, 读取这个配置类 达到自动配置的功能

  • @ConditionalOnMissingBean
    
    ////////////////////////////
    @Configuration
    @ConditionalOnProperty(name = "shiro.enabled", matchIfMissing = true)
    public class ShiroBeanAutoConfiguration extends AbstractShiroBeanConfiguration {
    
        @Bean
        @ConditionalOnMissingBean
        @Override
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return super.lifecycleBeanPostProcessor();
        }
    
        @Bean
        @ConditionalOnMissingBean
        @Override
        protected EventBus eventBus() {
            return super.eventBus();
        }
    
        @Bean
        @ConditionalOnMissingBean
        @Override
        public ShiroEventBusBeanPostProcessor shiroEventBusAwareBeanPostProcessor() {
            return super.shiroEventBusAwareBeanPostProcessor();
        }
    }
    
  • DependsOn是什么?

  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    //添加前缀判断 不匹配 任何Advisor
    defaultAdvisorAutoProxyCreator.setUsePrefix(true);
    defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
    return defaultAdvisorAutoProxyCreator;
  }
  • lifecycleBeanPostProcessor是什么
  • DefaultAdvisorAutoProxyCreator类做什么的?
  • defaultAdvisorAutoProxyCreator.setUsePrefix(true); 作用?
  • 自定义aop该怎么写?
  <!--
    3.使用AOP将事务切到Service层
  -->
  <aop:config>
    <!-- 配置切入点 -->
    <aop:pointcut id="txPointcut" expression="execution(* ${groupId}.service..*.*(..))" />
    <!-- 配置切面= 切入点+通知 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
  </aop:config>

  <aop:aspectj-autoproxy proxy-target-class="true" />
  <!-- <aop:config/> 会扫描配置文件中的所有advisor,并为其创建代理 -->
  <aop:config />
  <!-- Pointcut advisor通知器, 会匹配所有加了shiro权限注解的方法 -->
  <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="defaultWebSecurityManager" />
  </bean>
  • @Aspect
  • @Pointcut
  • @Around
  • @AfterThrowing

  • pointcut [ 称为切入点, 如 delete 方法 ]
  • advice[是个接口, 所以是行为的集合体] [ 称为增强 或者 通知, 即 删除之前 记录 谁在删除 删除谁 什么时候 ] [由 aspect 添加到特定的 join point(即满足 point cut 规则的 join point) 的一段代码]
  • advisor = advice + pointcut
  • aspect [称为切面, aspect 由 pointcount 和 advice 组成]
<aop:aspectj-autoproxy proxy-target-class="true" />

Aop自动创建代理对象的原理

我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的代理对象,以使用对应的Advisor。

前提是我们在使用Spring Aop时是使用的<aop:config/><aop:aspectj-autoproxy/>,

这是因为当我们在applicationContext.xml文件中通过<aop:config/>的形式定义需要使用Aop的场景时,Spring会自动为我们添加AspectjAwareAdvisorAutoProxyCreator类型的bean;

而我们定义了<aop:aspectj-autoproxy/>时,Spring会默认为我们添加AnnotationAwareAspectjAutoProxyCreator类型的bean。Spring中在bean实例化后能够对bean对象进行包装的是BeanPostProcessor,AspectjAwareAdvisorAutoProxyCreator和AnnotationAwareAspectjAutoProxyCreator都是实现了BeanPostProcessor接口的。

AnnotationAwareAspectjAutoProxyCreator的父类是AspectjAwareAdvisorAutoProxyCreator,而AspectjAwareAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreator,AbstractAdvisorAutoProxyCreator的父类是实现了BeanPostProcessor接口的AbstractAutoProxyCreator。它们的核心逻辑都是在bean初始化后找出bean容器中所有的能够匹配当前bean的Advisor

找到了则将找到的Advisor通过ProxyFactory创建该bean的代理对象返回。

AspectjAwareAdvisorAutoProxyCreator在寻找候选的Advisor时会找到bean容器中所有的实现了Advisor接口的bean,而AnnotationAwareAspectjAutoProxyCreator则在AspectjAwareAdvisorAutoProxyCreator的基础上增加了对标注了@Aspect的bean的处理,会附加上通过@Aspect标注的bean中隐式定义的Advisor。

所以这也是为什么我们在使用@Aspect标注形式的Spring Aop时需要在applicationContext.xml文件中添加<aop:aspectj-autoproxy/>

<aop:aspectj-autoproxy proxy-target-class="true" />

    <xsd:element name="aspectj-autoproxy">
        <xsd:annotation>
            <xsd:documentation source="java:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><![CDATA[
    Enables the use of the @AspectJ style of Spring AOP.

    See org.springframework.context.annotation.EnableAspectJAutoProxy Javadoc
    for information on code-based alternatives to this XML element.
            ]]></xsd:documentation>
        </xsd:annotation>

<aop:config>

<xsd:element name="config">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
    A section (compartmentalization) of AOP-specific configuration (including
    aspects, pointcuts, etc).
            ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="pointcut" type="pointcutType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation><![CDATA[
    A named pointcut definition.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
                <xsd:element name="advisor" type="advisorType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation source="java:org.springframework.aop.Advisor"><![CDATA[
    A named advisor definition.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
                <xsd:element name="aspect" type="aspectType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation><![CDATA[
    A named aspect definition.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
            </xsd:sequence>
            <xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Are class-based (CGLIB) proxies to be created? By default, standard
    Java interface-based proxies are created.
                    ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Indicate that the proxy should be exposed by the AOP framework as a
    ThreadLocal for retrieval via the AopContext class. Off by default,
    i.e. no guarantees that AopContext access will work.
                    ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

既然AspectjAwareAdvisorAutoProxyCreator和AnnotationAwareAspectjAutoProxyCreator都会自动扫描bean容器中的Advisor,

所以当我们使用了<aop:config/><aop:aspectj-autoproxy/>形式的Aop定义时,如果因为某些原因光通过配置满足不了你Aop的需求,而需要自己实现Advisor接口时(一般是实现PointcutAdvisor接口),那这时候你只需要把自己的Advisor实现类,定义为Spring的一个bean即可。

如果你在applicationContext.xml中没有定义<aop:config/><aop:aspectj-autoproxy/>,那你也可以直接在applicationContext.xml中直接定义AspectjAwareAdvisorAutoProxyCreator或AnnotationAwareAspectjAutoProxyCreator类型的bean,效果也是一样的。其实为了能够在创建目标bean的时候能够自动创建基于我们自定义的Advisor实现类的代理对象,我们的bean容器中只要有AbstractAutoProxyCreator类型的bean定义即可,当然了你实现自己的BeanPostProcessor,在其postProcessAfterInitialization方法中创建自己的代理对象也是可以的。但是本着不重复发明轮子的原则,我们尽量使用官方已经提供好的实现即可。

AbstractAutoProxyCreator是继承自ProxyConfig的,所以我们在定义AbstractAutoProxyCreator子类的bean时,我们也可以手动的定义一些ProxyConfig中包含的属性,比如proxyTargetClass、exposeProxy等。

AbstractAutoProxyCreator的子类除了AspectjAwareAdvisorAutoProxyCreator和AnnotationAwareAspectjAutoProxyCreator外,

我们可用的还有BeanNameAutoProxyCreator和DefaultAdvisorAutoProxyCreator。

BeanNameAutoProxyCreator

BeanNameAutoProxyCreator可以用来定义哪些bean可与哪些Advisor/Advice绑定,以生成对应的代理对象。

需要绑定的bean是通过beanNames属性来指定的,对应的是bean的名称,其中可以包含“”号,表示任意字符,比如“abc”则匹配任意名称以“abc”开始的bean;需要绑定的Advisor/Advice是通过interceptorNames来指定的,如果指定的是Advisor,那么是否可生成基于该Advisor的代理需要对应的bean能够匹配对应AdvisorPointcutAdvisor类型)的Pointcut;如果指定的是Advice,则该Advice会被包含在Pointcut恒匹配的Advisor中,即能够与所有的bean绑定生成对应的代理,且会对所有的方法调用起作用。 指定interceptorNames时是不能使用通配符的,只能精确的指定需要应用的Advisor/Advice对应的bean名称。

    <bean id="userService" class="com.elim.learn.spring.aop.service.UserServiceImpl"/>
    <bean id="myService" class="com.elim.learn.spring.aop.service.MyService"/>

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <!-- 匹配userService和所有名称以my开头的bean -->
        <property name="beanNames" value="userService, my*"/>
        <!-- interceptorNames中不能使用通配符,只能是精确匹配,即精确指定Advisor/Advice的bean名称 -->
        <property name="interceptorNames" value="logBeforeAdvice, myAdvisor "/>
    </bean>

    <bean id="logBeforeAdvice" class="com.elim.learn.spring.aop.advice.LogBeforeAdvice" />

    <bean id="myAdvisor" class="com.elim.learn.spring.aop.advisor.MyAdvisor"/>12345678910111213

如上就是一个使用BeanNameAutoProxyCreator建立指定的bean基于指定的Advisor/Advice的代理对象的示例。示例中我们指定interceptorNames时特意应用了一个Advisor实现和一个Advice实现。Advice会应用于所有绑定的bean的所有方法调用,而Advisor只会应用于其中的Pointcut能够匹配的方法调用。这里的源码我就不提供了,有兴趣的朋友可以自己试试。

DefaultAdvisorAutoProxyCreator

DefaultAdvisorAutoProxyCreator的父类也是AbstractAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreator的作用是会默认将bean容器中所有的Advisor都取到,如果有能够匹配某一个bean的Advisor存在,则会基于能够匹配该bean的所有Advisor创建对应的代理对象。需要注意的是DefaultAdvisorAutoProxyCreator在创建bean的代理对象时是不会考虑Advice的,只是Advisor。如上面的示例中,如果我们希望所有的bean都能够自动的与匹配的Advisor进行绑定生成对应的代理对象,那么我们可以调整配置如下。

    <bean id="userService" class="com.elim.learn.spring.aop.service.UserServiceImpl"/>
    <bean id="myService" class="com.elim.learn.spring.aop.service.MyService"/>

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    <bean id="myAdvisor" class="com.elim.learn.spring.aop.advisor.MyAdvisor"/>123456

使用DefaultAdvisorAutoProxyCreator时可能我们并不希望为所有的bean定义都自动应用bean容器中的所有Advisor,而只是希望自动创建基于部分Advisor的代理对象。这个时候如果我们期望应用自动代理的Advisor的bean定义的名称都是拥有固定的前缀时,则我们可以应用DefaultAdvisorAutoProxyCreatorsetAdvisorBeanNamePrefix(String)指定需要应用的Advisor的bean名称的前缀,同时需要通过setUsePrefix(boolean)指定需要应用这种前缀匹配机制。如我们的bean容器中有两个Advisor定义,一个bean名称是“myAdvisor”,一个bean名称是“youAdvisor”,如果只期望自动创建基于bean名称以“my”开始的Advisor的代理,则可以进行如下配置。

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <property name="usePrefix" value="true" />
        <!-- 匹配所有bean名称以my开始的Advisor -->
        <property name="advisorBeanNamePrefix" value="my" />
    </bean>

hutool中对aspect的理解

package cn.hutool.aop.aspects;

import java.lang.reflect.Method;

/**
 * 切面接口
 *
 * @author looly
 * @author ted.L
 * @since 4.18
 */
public interface Aspect {

    /**
     * 目标方法执行前的操作
     *
     * @param target 目标对象
     * @param method 目标方法
     * @param args   参数
     * @return 是否继续执行接下来的操作
     */
    boolean before(Object target, Method method, Object[] args);

    /**
     * 目标方法执行后的操作
     * 如果 target.method 抛出异常且
     *
     * @param target    目标对象
     * @param method    目标方法
     * @param args      参数
     * @param returnVal 目标方法执行返回值
     * @return 是否允许返回值(接下来的操作)
     * @see Aspect#afterException 返回true,则不会执行此操作
     * 如果
     * @see Aspect#afterException 返回false,则无论target.method是否抛出异常,均会执行此操作
     */
    boolean after(Object target, Method method, Object[] args, Object returnVal);

    /**
     * 目标方法抛出异常时的操作
     *
     * @param target 目标对象
     * @param method 目标方法
     * @param args   参数
     * @param e      异常
     * @return 是否允许抛出异常
     */
    boolean afterException(Object target, Method method, Object[] args, Throwable e);
}
public interface Advisor {

    /**
     * Common placeholder for an empty {@code Advice} to be returned from
     * {@link #getAdvice()} if no proper advice has been configured (yet).
     * @since 5.0
     */
    Advice EMPTY_ADVICE = new Advice() {};


    /**
     * Return the advice part of this aspect. An advice may be an
     * interceptor, a before advice, a throws advice, etc.
     * @return the advice that should apply if the pointcut matches
     * @see org.aopalliance.intercept.MethodInterceptor
     * @see BeforeAdvice
     * @see ThrowsAdvice
     * @see AfterReturningAdvice
     */
    Advice getAdvice();

    /**
     * Return whether this advice is associated with a particular instance
     * (for example, creating a mixin) or shared with all instances of
     * the advised class obtained from the same Spring bean factory.
     * <p><b>Note that this method is not currently used by the framework.</b>
     * Typical Advisor implementations always return {@code true}.
     * Use singleton/prototype bean definitions or appropriate programmatic
     * proxy creation to ensure that Advisors have the correct lifecycle model.
     * @return whether this advice is associated with a particular target instance
     */
    boolean isPerInstance();

}

spring AOP中 aop:advisor 与 aop:aspect 的区别

在开发过程中,不少有Spring Aop的使用, 在面向切面编程时,我们会使用< aop:aspect>; 在进行事务管理时,我们会使用< aop:advisor>。

那么,对于< aop:aspect>与< aop:advisor>的区别,具体是怎样的呢?

至于两者的区别,网上有很多资料,但是似乎都不能说清楚。 首先,我们需要明确两者的概念。

  • < aop:aspect>:定义切面(切面包括通知和切点)
  • < aop:advisor>:定义通知器(通知器跟切面一样,也包括通知和切点)

下面,我们列举两者的几个区别。

1、实现方式不同

< aop:aspect>定义切面时,只需要定义一般的bean就行, 而定义< aop:advisor>中引用的通知时,通知必须实现Advice接口。

下面我们举例说明。 首先,我们定义一个接口Sleepable和这个接口的实现Human,代码如下:

public interface Sleepable {
    public void sleep();
}
public class Human implements Sleepable {
    @Override
    public void sleep() {
        System.out.println("我要睡觉了!");
    }
}

下面是< aop:advisor>的实现方式:

//定义通知
public class SleepHelper implements MethodBeforeAdvice,AfterReturningAdvice{
    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        System.out.println("睡觉前要脱衣服!");
    }
    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        System.out.println("起床后要穿衣服!");
    }
}
//aop配置
<bean id="sleepHelper" class="com.ghs.aop.SleepHelper"></bean>
<aop:config>
    <aop:pointcut expression="execution(* *.sleep(..))" id="sleepPointcut"/>
    <aop:advisor advice-ref="sleepHelper" pointcut-ref="sleepPointcut"/>
</aop:config>
<bean id="human" class="com.ghs.aop.Human"/>

下面是< aop:aspect>的实现方式:

//定义切面
public class SleepHelperAspect{
    public void beforeSleep(){
        System.out.println("睡觉前要脱衣服!");
    }
    public void afterSleep(){
        System.out.println("起床后要穿衣服!");
    }
}
//aop配置
<bean id="sleepHelperAspect" class="com.ghs.aop.SleepHelperAspect"></bean>
<aop:config>
    <aop:pointcut expression="execution(* *.sleep(..))" id="sleepPointcut"/>
    <aop:aspect ref="sleepHelperAspect">
        <!--前置通知-->
        <aop:before method="beforeSleep" pointcut-ref="sleepPointcut"/>
        <!--后置通知-->
        <aop:after method="afterSleep" pointcut-ref="sleepPointcut"/>
    </aop:aspect>
</aop:config>
<bean id="human" class="com.ghs.aop.Human"/>

测试代码如下:

public class TestAOP {
    public static void main(String[] args) {
        method1();
//      method2();
    }
    private static void method1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
        Sleepable sleeper = (Sleepable) context.getBean("human");
        sleeper.sleep();
    }
    private static void method2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
        Sleepable sleeper = (Sleepable) context.getBean("human");
        sleeper.sleep();
    }
//执行结果
睡觉前要脱衣服!
我要睡觉了!
起床后要穿衣服!
}

2、使用场景不同

< aop:advisor>大多用于事务管理。 例如:

<!-- 会重复读,不会脏读事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" timeout="120" propagation="REQUIRED" rollback-for="Exception" />
    </tx:attributes>
</tx:advice>

<aop:config proxy-target-class="true">
    <aop:pointcut id="txPointCut" expression="..."/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>

< aop:aspect>大多用于日志,缓存。

其实,不管是< aop:advisor>还是< aop:aspect>最终的实现逻辑是一样的。

小结: 可以看出,< aop:advisor>和< aop:aspect>其实都是将通知和切面进行了封装,原理基本上是一样的,只是使用的方式不同而已。

附: 对于这个问题的理解,其实尚未有一个深入的认识,下面推荐大家几篇博文,希望共同交流。 http://www.iteye.com/problems/69785 http://blog.sina.com.cn/s/blog_5198c7370100hw1p.html http://blog.csdn.net/huitoukest/article/details/46469177 http://www.tz365.cn/ask/shenghuo/2016/0804/739237.html https://zhidao.baidu.com/question/371238289198208804.html ---------------------

原文:https://blog.csdn.net/u011983531/article/details/70504281


<aop:aspectj-autoproxy />

<xsd:element name="aspectj-autoproxy">
        <xsd:annotation>
            <xsd:documentation source="java:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><![CDATA[
    Enables the use of the @AspectJ style of Spring AOP.

    See org.springframework.context.annotation.EnableAspectJAutoProxy Javadoc
    for information on code-based alternatives to this XML element.
            ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="include" type="includeType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation><![CDATA[
    Indicates that only @AspectJ beans with names matched by the (regex)
    pattern will be considered as defining aspects to use for Spring autoproxying.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
            </xsd:sequence>
            <xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Are class-based (CGLIB) proxies to be created? By default, standard
    Java interface-based proxies are created.
                    ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Indicate that the proxy should be exposed by the AOP framework as a
    ThreadLocal for retrieval via the AopContext class. Off by default,
    i.e. no guarantees that AopContext access will work.
                    ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

proxy-target-class 默认是false

proxy-target-class="true" 与proxy-target-class="false"的区别

proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。

基于接口,使用JDK动态代理

基于类,需要使用cglib库


proxy-target-class="true" 表示强制使用 CGLIB 技术来实现AOP,因为CGLIB是生成子类也就是代理类来实现的,所以proxy-target-class,表示是否代理目标类。

就会由spring来选择,spring优先使用JDK动态代理来实现AOP。

<xsd:element name="config">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
    A section (compartmentalization) of AOP-specific configuration (including
    aspects, pointcuts, etc).
            ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="pointcut" type="pointcutType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation><![CDATA[
    A named pointcut definition.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
                <xsd:element name="advisor" type="advisorType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation source="java:org.springframework.aop.Advisor"><![CDATA[
    A named advisor definition.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
                <xsd:element name="aspect" type="aspectType" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation><![CDATA[
    A named aspect definition.
                        ]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
            </xsd:sequence>
            <xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Are class-based (CGLIB) proxies to be created? By default, standard
    Java interface-based proxies are created.
                    ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Indicate that the proxy should be exposed by the AOP framework as a
    ThreadLocal for retrieval via the AopContext class. Off by default,
    i.e. no guarantees that AopContext access will work.
                    ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

Spring AOP 不同配置方式产生的冲突问题

命名空间解析 原来是NamespaceHandlerSupport

image-20210129134418470


DefaultAdvisorAutoProxyCreator 配置

   <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
       <property name="proxyTargetClass" value="true"/>
   </bean>

results matching ""

    No results matching ""