Spring 从入门到精通 (十九) AOP坑

举报
周棋洛 发表于 2022/07/27 23:03:39 2022/07/27
【摘要】 关键词:Spring | AOP | 踩坑 本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨ 目录 一、什么坑?...

关键词:Spring | AOP | 踩坑

本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨

在这里插入图片描述

一、什么坑?

同一类中进行方法间的相互调用,只有最外层的方法会被代理并加入额外功能,内部调用的方法,比如使用 this.方法() 这里 this 指的是普通类对象,所以不会被代理

二、复现坑

下面举个例子看看这个坑

去修改业务层代码,让其互相调用

UserServiceImpl

public class UserServiceImpl implements UserService{
    @Override
    public void login(String name, String pwd1) {
        System.out.println("处理核心业务用户登录,并调用DAO~~~~");
        // 调用了注册方法,它不会被代理
        this.register(new User());
    }

    @Override
    public void register(User user) {
        System.out.println("处理核心业务用户注册,并调用DAO~~~~");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

编写测试类,获取实例,执行方法

Test测试

@Test
public void t3() {
    ApplicationContext con = new ClassPathXmlApplicationContext("/spring.xml");
    UserService userService = (UserService) con.getBean("userService");
    userService.login("asd", "asda");
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

测试结果:

工厂加工了,拿到返回了代理对象
处理核心业务用户登录,并调用DAO~~~~
处理核心业务用户注册,并调用DAO~~~~

  
 
  • 1
  • 2
  • 3

用户登录即 login() 被代理了,而在 login() 中调用的 register() 没有被代理,是Spring有问题吗?其实不然,仔细观察调用的具体写法 this.register() this指的是本类,即 UserServiceImpl 类,显然你调用的就不是代理类的注册方法,所以这结果很正常

那我们怎么让,互相调用的时候,也可以被代理呢?我们想用代理对象来调用这个方法不就好了,下面开始填坑

三、填坑

实现 ApplicationContextAware 接口,Spring就会把工厂通过 set 注入给我们,我们声明一个成员变量,并通过set方法赋值一下应用,这样就有一个全局工厂应用了

为什么不 new 一个工厂,搞这么麻烦 ?

Spring工厂是重量级资源,一个应用应该只创建一个工厂实例


public class UserServiceImpl implements UserService, ApplicationContextAware {

    private ApplicationContext context;

    // 实现了 ApplicationContextAware 接口,Spring就会把工厂通过 set 注入给我们
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    @Override
    public void login(String name, String pwd1) {
        System.out.println("处理核心业务用户登录,并调用DAO~~~~");
        // 通过工厂调用,此时获取的是代理对象
        UserService userService = (UserService) context.getBean("userService");
        userService.register(new User());
    }

    @Override
    public void register(User user) {
        System.out.println("处理核心业务用户注册,并调用DAO~~~~");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

再次测试

@Test
public void t3() {
    ApplicationContext con = new ClassPathXmlApplicationContext("/spring.xml");
    UserService userService = (UserService) con.getBean("userService");
    userService.login("asd", "asda");
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
工厂加工了,拿到返回了代理对象
处理核心业务用户登录,并调用DAO~~~~
工厂加工了,拿到返回了代理对象
处理核心业务用户注册,并调用DAO~~~~

  
 
  • 1
  • 2
  • 3
  • 4

现在业务方法相互调用,都被代理了,解决了这个问题,思路就是确保调用的时候是使用代理对象进行调用的,而不是原始对象进行调用的,就可以了,最简单的 new 工厂,但是Spring工厂是重量级的,一个应用只启动一个就好了,因此使用一些特殊技巧,获得工厂的引用就可以了

四、写在最后

座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!

一起学习的可以私信博主或添加博主微信哦。

专栏:订阅专栏 ✅
关注:关注博主 🆙

文章来源: blog.csdn.net,作者:王子周棋洛,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/m0_53321320/article/details/126000992

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。