主页 > 开源代码  > 

代理对象中使用this

代理对象中使用this
一、问题引出

业务逻辑层代码

@Service public class DemoServiceImpl extends ServiceImpl<DemoMapper, Demo> implements DemoService, ApplicationContextAware { // 用于从Spring容器中获取指定Bean的对象 private ApplicationContext applicationContext; // 通过ApplicationContextAware接口完成applicationContext对象的注入 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void methodC() { System.out.println("使用this调用结果:"); this.methodD(); System.out.println("\n使用Bean对象调用结果:"); DemoServiceImpl bean = applicationContext.getBean(DemoServiceImpl.class); bean.methodD(); } public void methodD() { System.out.println("执行D方法……"); } }

自定义切面:对DemoServiceImpl方法中的methodD方法进行增强,在前后打印相关内容

@Aspect @Component public class CustomAspect { @Around("execution(* com.example.service.*.methodD(..))") public void aspectMethod(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("aspectMethod before执行……"); joinPoint.proceed(); System.out.println("aspectMethod after执行……"); } }

测试类

@SpringBootTest class DemoApplicationTests { @Test void contextLoads() { } @Resource private DemoService demoService; @Test void test() throws Exception { demoService.methodC(); } }

测试结果:

使用this调用结果: 执行D方法…… 使用Bean对象调用结果: aspectMethod before执行…… 执行D方法…… aspectMethod after执行……

**疑问:**之前学习的时候不是说this不是哪个对象调用就是哪个对象的引用类型(之间的理解有问题,应该是this始终指向当前对象的实例。在实例方法中,this 指向当前对象的实例;在构造方法中,this 指向正在被构造的对象),现在是通过demoService的代理对象(通过AOP进行增强,Spring在创建Bean对象的时候,会对该对象进行代理增强,并放入到IOC容器中)对methodC方法的调用,然后methodC中又通过this去调用methodD方法,那这个this不就是demoService的代理对象吗?methodD不就应该是代理对象的methodD,即增强后的methodD方法吗,但是实际上确实增强前的MethodD方法。

二、原因分析

首先this是Java语言的一个关键字,指向当前对象的实例:

注意:如果通过代理对象调用方法,this 仍然指向 原始对象,而不是代理对象,因为 this 是 Java 语言的关键字,它的行为是由 Java 语言规范定义的,无法被 Spring 或其他框架修改。

this 的行为在编译期就已经确定,编译器会将 this 替换为当前对象的引用:

public class A { public void method() { System.out.println("Method called"); } public static void main(String[] args) { A a = new A(); a.method(); } }

其在编译后等价于:

public class A { public void method(A this) { System.out.println("Method called"); } public static void main(String[] args) { A a = new A(); a.method(a); } }

在实例方法调用时,编译器会隐式地将当前对象的引用作为第一个参数传递给方法,通过查看A对应的字节码可以看到,methodC方法的局部变量表中的第一个参数就是this,因此,this关键字实际上就是一个指向当前对象的隐式参数。

因此在上面的DemoServiceImpl的methodC方法中通过this调用methodD方法的时候,其实就是调用DemoServiceImpl实例对象的methodD方法,而不是Spring AOP代理对象的methodD方法,this 是在编译期确定的,指向 DemoServiceImpl 的实例。而通过Spring AOP创建的代理对象是在 运行时 动态生成的,this 仍然指向原始对象。

我们打一个断点,也可以看到this和bean这两个对象是不一样的,this就是DemoServiceImpl实例对象,而bean是通过Spring AOP增强后的代理对象(使用GCLIB进行代理)

总结:

this 是在编译期确定的:它指向当前对象的实例,无法被运行时修改。代理对象是运行时生成的:Spring 的代理对象无法改变 this 的行为。 尾言 参考文章 blog.csdn.net/benxiangsj/article/details/124282800 blog.csdn.net/weixin_53840353/article/det
标签:

代理对象中使用this由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“代理对象中使用this