AOP 简介 Aop(Aspect Oriented Programming),面向切面编程,这是对面向对象思想的一种补充。
面向切面编程,就是在程序运行时,不改变程序源码的情况下,动态的增强方法的功能,常见的使用场景非常多:
日志
事务
数据库操作
….
这些操作中,无一例外,都有很多模板化的代码,而解决模板化代码,消除臃肿就是 Aop 的强项。在 Aop 中,有几个常见的概念:
概念
说明
切点
要添加代码的地方,称作切点
通知(增强)
通知就是向切点动态添加的代码
切面
切点 + 通知
连接点
切点的定义
AOP 的实现 在 Aop 实际上集基于 Java 动态代理来实现的。Java 中的动态代理有两种实现方式:
动态代理 基于 JDK 的动态代理实例。
1. 定义一个计算器接口
1 2 3 4 public interface MyCalculator { int add (int a, int b) ; }
2. 定义计算机接口的实现
1 2 3 4 5 6 public class MyCalculatorImpl implements MyCalculator { public int add (int a, int b) { return a + b; } }
3. 定义代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class CalculatorProxy { public static Object getInstance (final MyCalculatorImpl myCalculator) { return Proxy.newProxyInstance(CalculatorProxy.class .getClassLoader (), myCalculator .getClass ().getInterfaces (), new InvocationHandler () { public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()+"方法开始执行啦..." ); Object invoke = method.invoke(myCalculator, args); System.out.println(method.getName()+"方法执行结束啦..." ); return invoke; } }); } }
Proxy.newProxyInstance 方法接收三个参数,第一个是一个 classloader,第二个是代理多项实现的接口,第三个是代理对象方法的处理器,所有要额外添加的行为都在 invoke 方法中实现。
XML 配置 AOP 1. 在 pom.xml 中引入 Spring 和 AOP 相关依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 5.1.9.RELEASE</version > </dependency > <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjweaver</artifactId > <version > 1.9.5</version > </dependency > <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjrt</artifactId > <version > 1.9.5</version > </dependency >
2. 接下来,定义通知/增强,但是单纯定义自己的行为即可,不再需要注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class LogAspect { public void before (JoinPoint joinPoint) { Signature signature = joinPoint.getSignature(); String name = signature.getName(); System.out.println(name + "方法开始执行了..." ); } public void after (JoinPoint joinPoint) { Signature signature = joinPoint.getSignature(); String name = signature.getName(); System.out.println(name + "方法执行结束了..." ); } public void returing (JoinPoint joinPoint,Integer r) { Signature signature = joinPoint.getSignature(); String name = signature.getName(); System.out.println(name + "方法返回:" +r); } public void afterThrowing (JoinPoint joinPoint,Exception e) { Signature signature = joinPoint.getSignature(); String name = signature.getName(); System.out.println(name + "方法抛异常了:" +e.getMessage()); } public Object around (ProceedingJoinPoint pjp) { Object proceed = null ; try { proceed = pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } return proceed; } }
3. 接下来在 Spring 中配置 AOP
1 2 3 4 5 6 7 8 9 10 11 12 <bean class ="com.antoniopeng.hello.spring.aop.LogAspect" id ="logAspect" /> <aop:config > <aop:pointcut id ="pc1" expression ="execution(* com.antoniopeng.hello.spring.aop.commons.*.*(..))" /> <aop:aspect ref ="logAspect" > <aop:before method ="before" pointcut-ref ="pc1" /> <aop:after method ="after" pointcut-ref ="pc1" /> <aop:after-returning method ="returing" pointcut-ref ="pc1" returning ="r" /> <aop:after-throwing method ="afterThrowing" pointcut-ref ="pc1" throwing ="e" /> <aop:around method ="around" pointcut-ref ="pc1" /> </aop:aspect > </aop:config >
4. 最后,在 Main 方法中加载配置文件
1 2 3 4 5 6 7 8 public class Main { public static void main (String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml" ); MyCalculatorImpl myCalculator = ctx.getBean(MyCalculatorImpl.class ) ; myCalculator.add(3 , 4 ); myCalculator.min(5 , 6 ); } }
本文发于:https://antoniopeng.com
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !