AOP
AOP:Aspect Oriented Programming 面向切面编程
优点:
- 降低模块之间的耦合度
- 使系统容易扩展
- 更好的代码复用
- 非业务代码更加集中,不分散,便于统一管理
- 约为代码更加纯粹,没有其他代码的影响
AOP 是对面向对象编程的一个补充,在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面编程。将不同方法的同一个位置抽象成一个切面对象,对该切面对象进行编程就是 AOP 。
如何使用
- 创建 Maven 工程,pom.xml 添加
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
- 创建一个计算器接口 Cal,定义四个方法。
package utils;
public interface Cal {
public int add(int num1, int num2);
public int sub(int num1, int num2);
public int mul(int num1, int num2);
public int div(int num1, int num2);
}
- 创建接口的实现类 CalImp
package utils.imp;
import utils.Cal;
public class CalImp implements Cal {
public int add(int num1, int num2) {
int result=num1+ num2;
System.out.println("add");
System.out.println("结果为"+result);
return result;
}
public int sub(int num1, int num2) {
int result=num1- num2;
System.out.println("sub");
System.out.println("结果为"+result);
return result;
}
public int mul(int num1, int num2) {
int result=num1*num2;
System.out.println("mul");
System.out.println("结果为"+result);
return result;
}
public int div(int num1, int num2) {
int result=num1/num2;
System.out.println("div");
System.out.println("结果为"+result);
return result;
}
}
上述代码中,日志信息和业务逻辑的耦合性很高,不利于系统维护,使用 AOP 可以进行优化。
使用动态代理的方式来实现。
给业务代码找一个代理,打印日志信息的工作交给代理来做,这样的话业务代码就只需要关注自身的业务即可。
原理实现&&底层实现
public class MyInvocationHandler implements InvocationHandler {
//接收委托对象
private Object object=null;
//返回代理对象
public Object bind(Object object){
this.object=object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法名:"+method.getName()+",参数是:"+ Arrays.toString(args));
Object result = method.invoke(this.object,args);
System.out.println("结果是"+result);
return result;
}
}
public class Test {
public static void main(String[] args) {
MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
Cal cal=new CalImp();
Cal cal_proxy=(Cal) myInvocationHandler.bind(cal);
cal_proxy.add(2,5);
cal_proxy.sub(2,5);
cal_proxy.mul(2,5);
cal_proxy.div(2,5);
}
}
以上是通过动态代理实现AOP过程,比较复杂,不好理解,Spring 框架对 AOP 进行了封装, 可以用面向对象的思想来实现 AOP。
Spring 框架中不需要创建 InvocationHandler ,只需要创建一个切面对象,将所有的非业务代码再切面对象中完即可。Spring 框架底层会自动根据切面类以及目标类生成一个代理对象。