Spring的Aop调用当前类的两种方法

Easter79
• 阅读 615

我们知道Spring对于AOP实现有两种方法,如果类是接口实现类,则采用JDK动态代理实现AOP。如果类没有实现接口,则采用cglib生成子类做增强,以实现代理类的目的,其实运行时找到的是这个代理类,而不是原类。

所以在一个代理类中调用内部的方法,是不是再走AOP逻辑的,那有什么好的方法可以解决这种问题吗?

基于上面的思路有两种解决办法

方法一:直接从BeanFactory中获取再次代理Bean 示例代码如下:

@Service
public class DemoService implements IDemoService {
    
    @Autowired
    private ApplicationContext context;
    
    public String demoHello(){
        System.out.println("hello");
        final IDemoService bean = context.getBean(IDemoService.class);
        bean.normalHello();
        return "hello";
    }
}

即继续调用代理类的normalHello()方法。

方法二:从AopContext中获取代理Bean

SpringAop有一个配置参数exposeProxy 如果配置为true ,可以让代理对象的方法被调用时把代理对象放入AopContext,这个配置的定义如下(ps:看看这个配置的注释说明):

//org.springframework.context.annotation.EnableAspectJAutoProxy
/**
 * 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;

所以代码还可以这样写:启动类EnableAspectJAutoProxy注解改为

@EnableAspectJAutoProxy(exposeProxy = true)
DemoService 类demoHello()方法改为:

    public String demoHello(){
        System.out.println("hello");
        final IDemoService bean = (IDemoService) AopContext.currentProxy();
        bean.normalHello();
        return "hello";
    }

exposeProxy 属性如何生效的?

在这里拓展一点点,关于Aop有两个很重要的方法, 代理类增强方法被调用时会进入这两个个方法中的其中一个,基于代理方式:

CglibAopProxy.DynamicAdvisedInterceptor#intercept //Cglib代理方式
JdkDynamicAopProxy#invoke //JDK 代理方式

这两个被代理类的方法在执行的时候都有这么一段代码:

if (this.advised.exposeProxy) {
    // Make invocation available if necessary.
    oldProxy = AopContext.setCurrentProxy(proxy);
    setProxyContext = true;
}

因为进入了intercept或者invoke方法,那么表示正在调用proxy这个代理类的某个方法,那么就把代理类放入Aop 上下文。

当然最好的一种方法,是将不同的功能放到不同的类里面,这样调用起来就不是调用当前类了。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
@Transactional注解详细解读
@Transactional注解可以作用于接口、接口方法、类以及类方法上1\.当作用于类上时,该类的所有public方法将都具有该类型的事务属性2\.当作用在方法级别时会覆盖类级别的定义3\.当作用在接口和接口方法时则只有在使用基于接口的代理时它才会生效,也就是JDK动态代理,而不是Cglib代理4\.当在protect
Wesley13 Wesley13
2年前
CGLIB介绍与原理(通过继承的动态代理)
一、什么是CGLIB?CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。二、CGLIB原理CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的
Easter79 Easter79
2年前
Spring的两种代理JDK和CGLIB的区别浅谈
一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以
Stella981 Stella981
2年前
Spring AOP 两种代理 Cglib、JDK
概念AOP:AOP是OOP(面向对象编程)的一种延续,OOP中继承的思想主要是提高代码的重用率,但是继承不能同个类在多个方法的相同位置出现的相同代码的问题JDK动态代理:AOP的一种实现,仅支持实现了接口的类。性能较好Cglib:AOP的一种实现,支持实现了接口的类和没有实现接口的类。对比JDK动态代理性能较差SpringAOP:结
Wesley13 Wesley13
2年前
Java 动态代理实践AOP
大家都知道Spring中AOP是通过Java动态代理实现的,今天就来简单学习下demo。Java动态代理主要有两个核心类,InvocationHandler和Proxy。/{@codeInvocationHandler}istheinterfaceimplementedbythe<iinvo
Stella981 Stella981
2年前
SpringAOP动态代理技术自动生成代理类原理演示
//如下是自动生成代理类的逻辑演示:为了解耦合将类的方法单纯在代理类里调用;额外功能都在代理类里实现代理类的存在的问题就是开发代码量大代码冗余.为了解决这类问题使用AOP动态代理自动生成代理类publicinterfaceMan{publicvoidalive();//提供一个接口}public
Wesley13 Wesley13
2年前
CGLIB代理基础
  本文意在讲解CGLIB的基础使用及基本原理。一、CGLIB的基本原理:  依赖ASM字节码工具,通过动态生成实现接口或继承类的类字节码,实现动态代理。  针对接口,生成实现接口的类,即implements方式;针对类,生成继承父类的类,即extends方式。二、为什么使用CGLIB?  JDK的动态代理只能基于接口,有时候我们想基于类
Easter79 Easter79
2年前
Spring的两种动态代理:Jdk和Cglib 的区别和实现
一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以
Wesley13 Wesley13
2年前
AOP的自动代理
Spring的aop机制提供两类方式实现类代理。一种是单个代理,一种是自动代理。单个代理通过ProxyFactoryBean来实现(就如上面的配置)。自动代理:自动代理能够让切面定义来决定那个bean需要代理,不需要我们为特定的bean明确的创建代理从而提供一个更完整的aop实现通过BeanNameAutoProxyCreator或者Defaul
Easter79 Easter79
2年前
Spring概念和Bean管理(配置文件)
Spring概念1.spring是开源的轻量级框架(免费,依赖少,可以直接使用)2.spring核心主要两部分:  (1)aop:面向切面编程,扩展功能不是修改源代码实现  (2)ioc:控制反转,  比如有个类,在类里面有个方法(不是静态方法),调用类里面的方法,需要创建类的对象,使用对象调用方法,创
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k