Spring AOP
2020-12-13 05:14
标签:info int 用户 面向切面 总经理 create 新建 类加载 system AOP简介 Spring AOP的2种代理 AOP全称Aspect-Oriented Programming,即面向切面编程,它是面向对象编程(OOP)的一种补充。 在通常的业务处理中,都会进行事务处理、日志记录等操作,比如: 这是一个操作用户的类,是对用户的抽象,日志操作和用户操作其实没有半毛钱关系,上面的抽象并不好,把用户操作和日志操作杂糅在一起,应该把日志操作分离出去,这样才符合OOP的编程思想。 而且后期不好维护、升级,比如后面要修改日志操作,你找到User类,在addUser()中一部分是用户操作,一部分是日志操作,你要先找到哪些是日志操作,然后改。后面的方法也是如此,很繁琐。 AOP解决了此问题。AOP是一种新的编程思想,是OOP的一种补充。OOP专心负责核心业务,AOP负责其它杂七杂八的业务。 OOP好比是经理,AOP好比是助理。原先所有事儿,什么批文件、见客户、通知下级来开会、向下级传达指示,所有事儿都是自己做,很繁琐,搞得精疲力竭,还容易出问题。 现在招了助理AOP,总经理OOP可以专心处理核心的业务,批示下文件、见见客户就行了。传递指示、通知下级开会,这些事儿助理AOP来做。分工明确,效率 高很多。 这些操作往往可以被多个类使用的,所以叫做一个切面(Aspect)。 目前最流行的AOP框架有2个:Spring AOP和AspectJ。 在Spring AOP中,spring是通过代理(proxy)实现的AOP。有2种代理方式:JDK动态代理、CGLIB代理。 1、新建包jdk_proxy,用来写代理类、被代理类。包下新建UserInterface接口 包下新建一个实现类User 这些是要被代理的类。 2、新建包aspect,用来写切面中要使用方法(类)。包下新建类MyAspect 3、在jdk_proxy包下,新建JdkProxy类,要实现InvocationHandler接口(只有invoke()方法) 这是代理类,用来代理User类/UserInterface接口。 4、 新建一个test包,用来写测试类。包下新建类Test 5、运行,看到控制台输出如下 已自动调用AOP(前增强+后增强)、OOP(业务本身)中的方法。 因为JDK动态代理的JdkProxy类中的createProxy()方法中 Class[] classArr=user.getClass().getInterfaces(); //获取目标接口实例实现的全部接口 ,要用到目标对象的所实现的全部接口,就是说被代理的OOP的核心业务类必须要实现接口。 如果被代理的类没有实现接口,则可以使用CGLIB代理。 1、新建一个cglib包,用来写代理类、被代理类。包下新建User类(被代理类),不必实现接口 2、新建包aspect,包下新建切面类MyAspect 3、在cglib包下新建CglibProxy类(代理类),需实现MethodInterceptor接口(只有intercept()方法)。注意是org.springframework.cglib.proxy.MethodInterceptor接口,不是其他包下的MethodInterceptor接口。 4、新建包test,包下新建测试类Test 5、运行,控制台输出如下 说明:JDK动态代理需要目标类(被代理的类)实现接口,CGLIB代理不需要目标类实现接口。 Spring AOP 标签:info int 用户 面向切面 总经理 create 新建 类加载 system 原文地址:https://www.cnblogs.com/chy18883701161/p/11135435.html目录
AOP简介
1 class User{
2 public void addUser(){
3 ...... //添加用户
4 ....... //记录一条日志:xxx时间添加xxx用户,操作者:xxx,操作结果:xxx
5 }
6
7 public void alterUser(){
8 ....... //修改用户
9 ........//记录一条日志:xxx时间修改xxx用户,操作者:xxx,操作结果:xxx
10 }
11
12 public void deleteUser(){
13 .......//删除用户
14 .......//记录一条日志:xxx时间删除xxx用户,操作者:xxx,操作结果:xxx
15 }
Spring AOP
JDK动态代理
1 public interface UserInterface {
2 public void addUser();
3 public void alterUser();
4 public void deleteUser();
5 }
1 public class User implements UserInterface {
2 @Override
3 public void addUser() {
4 //模拟添加用户
5 System.out.println("正在添加用户");
6 System.out.println("添加用户成功");
7 }
8
9 @Override
10 public void alterUser() {
11 //模拟修改用户信息
12 System.out.println("正在修改用户信息");
13 System.out.println("修改用户信息成功");
14 }
15
16 @Override
17 public void deleteUser() {
18 //模拟删除用户
19 System.out.println("正在删除用户");
20 System.out.println("删除用户成功");
21 }
22 }
1 public class MyAspect {
2 //模拟检查权限
3 public boolean checkPermission(){
4 System.out.println("正在检查权限");
5 System.out.println("权限已够");
6 return true;
7 }
8
9 //模拟日志
10 public void log(){
11 System.out.println("正在写入日志");
12 System.out.println("xxx时间,xxx进行xxx操作,操作结果:xxx");
13 System.out.println("日志写入完毕");
14 }
15 }
1 public class JdkProxy implements InvocationHandler {
2 //声明目标接口的实例
3 private UserInterface user;
4
5 //创建代理方法,参数是目标接口的实例
6 public Object createProxy(UserInterface user){
7 this.user=user; //初始化目标接口实例
8
9 ClassLoader classLoader=JdkProxy.class.getClassLoader(); //获取当前类的类加载器,当前类类名.class.getClassLoader()
10 Class[] classArr=user.getClass().getInterfaces(); //获取目标接口实例实现的全部接口
11
12 //参数:当前类的类加载器,目标接口实例实现的所有接口,当前类的实例
13 return Proxy.newProxyInstance(classLoader,classArr,this);
14 }
15
16 @Override
17 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
18 //声明切面
19 MyAspect myAspect=new MyAspect();
20
21 //前增强,执行切面中的方法,在执行目标类中的方法之前做一些操作,比如检查权限。根据需要选用。
22 myAspect.checkPermission();
23
24 //执行目标类中的方法。比如addUser()。第一个参数目标对象,第二个是固定的
25 Object object=method.invoke(user,args);
26
27 //后增强。执行切面中的方法,在执行目标类中的方法之后做一些操作,比如记录日志。根据需要选用。
28 myAspect.log();
29
30 return object;
31 }
32 }
1 public class Test {
2 public static void main(String[] args) {
3 //JdkProxy的实例
4 JdkProxy jdkProxy=new JdkProxy();
5
6 //创建目标对象
7 UserInterface user=new User();
8
9 //通过JdkProxy类的实例动态创建user的代理,因为返回值是Object,需要强制类型转换,必须用目标接口转换,不能用实现类转换
10 UserInterface userProxy=(UserInterface) jdkProxy.createProxy(user);
11
12 //通过代理调用方法,会自动调用OOP、AOP中的相关方法。
13 userProxy.addUser();
14 }
15 }
正在检查权限
权限已够
正在添加用户
添加用户成功
正在写入日志
xxx时间,xxx进行xxx操作,操作结果:xxx
日志写入完毕
模型分析
AOP术语
CGLIB代理
1 public class User{
2 public void addUser() {
3 //模拟添加用户
4 System.out.println("正在添加用户");
5 System.out.println("添加用户成功");
6 }
7
8 public void alterUser() {
9 //模拟修改用户信息
10 System.out.println("正在修改用户信息");
11 System.out.println("修改用户信息成功");
12 }
13
14 public void deleteUser() {
15 //模拟删除用户
16 System.out.println("正在删除用户");
17 System.out.println("删除用户成功");
18 }
19 }
1 public class MyAspect {
2 //模拟检查权限
3 public boolean checkPermission(){
4 System.out.println("正在检查权限");
5 System.out.println("权限已够");
6 return true;
7 }
8
9 //模拟日志
10 public void log(){
11 System.out.println("正在写入日志");
12 System.out.println("xxx时间,xxx进行xxx操作,操作结果:xxx");
13 System.out.println("日志写入完毕");
14 }
15 }
1 public class CglibProxy implements MethodInterceptor {
2 //创建代理,参数是Object类型
3 public Object createProxy(Object target){
4 Enhancer enhancer=new Enhancer(); //创建一个动态类对象
5 enhancer.setSuperclass(target.getClass()); //将这个动态类对象的父类/基类设置为目标类(需要增强的类)
6 enhancer.setCallback(this); //设置回调
7 return enhancer.create(); //返回创建的代理
8 }
9
10 @Override
11 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
12 //创建切面实例
13 MyAspect myAspect=new MyAspect();
14
15 //前增强
16 myAspect.checkPermission();
17
18 //执行目标方法,参数:形参表的第一个参数、第三个参数
19 Object object=methodProxy.invokeSuper(o,objects);
20
21 //后增强
22 myAspect.log();
23
24 //返回代理对象
25 return object;
26 }
27 }
1 public class Test {
2 public static void main(String[] args) {
3 //创建CglibProxy的实例
4 CglibProxy cglibProxy=new CglibProxy();
5
6 //创建目标对象
7 User user=new User();
8
9 //通过CglibProxy类的实例创建user的代理,因为返回值是Object,需要强制类型转换,
10 User userProxy=(User)cglibProxy.createProxy(user);
11
12 //通过代理调用方法,会自动调用OOP、AOP中的相关方法。
13 userProxy.addUser();
14 }
15 }
正在检查权限
权限已够
正在添加用户
添加用户成功
正在写入日志
xxx时间,xxx进行xxx操作,操作结果:xxx
日志写入完毕