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~~~~");
    }
}

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

Test测试

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

测试结果:

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

用户登录即 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~~~~");
    }
}

再次测试

@Test
public void t3() {
    ApplicationContext con = new ClassPathXmlApplicationContext("/spring.xml");
    UserService userService = (UserService) con.getBean("userService");
    userService.login("asd", "asda");
}
工厂加工了,拿到返回了代理对象
处理核心业务用户登录,并调用DAO~~~~
工厂加工了,拿到返回了代理对象
处理核心业务用户注册,并调用DAO~~~~

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

四、写在最后

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

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

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

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王子周棋洛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值