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

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

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

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

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

1@Service 2public class DemoService implements IDemoService { 3 4 @Autowired 5 private ApplicationContext context; 6 7 public String demoHello(){ 8 System.out.println("hello"); 9 final IDemoService bean = context.getBean(IDemoService.class); 10 bean.normalHello(); 11 return "hello"; 12 } 13}

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

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

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

1//org.springframework.context.annotation.EnableAspectJAutoProxy 2/** 3 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} 4 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. 5 * Off by default, i.e. no guarantees that {@code AopContext} access will work. 6 * @since 4.3.1 7 */ 8boolean exposeProxy() default false;

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

1@EnableAspectJAutoProxy(exposeProxy = true) 2DemoService 类demoHello()方法改为: 3 4 public String demoHello(){ 5 System.out.println("hello"); 6 final IDemoService bean = (IDemoService) AopContext.currentProxy(); 7 bean.normalHello(); 8 return "hello"; 9 }

exposeProxy 属性如何生效的?

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

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

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

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

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

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

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

@Transactional注解详细解读

@Transactional注解可以作用于接口、接口方法、类以及类方法上1\.当作用于类上时,该类的所有public方法将都具有该类型的事务属性2\.当作用在方法级别时会覆盖类级别的定义3\.当作用在接口和接口方法时则只有在使用基于接口的代理时它才会生效,也就是JDK动态代理,而不是Cglib代理4\.当在protect

CGLIB介绍与原理(通过继承的动态代理)

一、什么是CGLIB?CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。二、CGLIB原理CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的

Spring的两种代理JDK和CGLIB的区别浅谈

一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以

Spring AOP 两种代理 Cglib、JDK

概念AOP:AOP是OOP(面向对象编程)的一种延续,OOP中继承的思想主要是提高代码的重用率,但是继承不能同个类在多个方法的相同位置出现的相同代码的问题JDK动态代理:AOP的一种实现,仅支持实现了接口的类。性能较好Cglib:AOP的一种实现,支持实现了接口的类和没有实现接口的类。对比JDK动态代理性能较差SpringAOP:结

Java 动态代理实践AOP

大家都知道Spring中AOP是通过Java动态代理实现的,今天就来简单学习下demo。Java动态代理主要有两个核心类,InvocationHandler和Proxy。/{@codeInvocationHandler}istheinterfaceimplementedbythe<iinvo