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
- 点赞
- 收藏
- 关注作者
评论(0)