AOP 面向切面编程
Aspect Oriented Programming
最基本的实现原理是一种代理模式(跟装饰模式很像),
所谓代理模式就是:原始类的方法功能都不够强,于是不使用原始类,而是在原始类上的基础上写代理类。java中可以通过一个原始类得到一个代理类。
装饰模式:当原始类的原始方法不好用,于是继承原始类,重写里面的方法。
新建包结构:
新建JDK代理工厂类:JDKProxyFactory.java
package net.seehope.spring.demo.ioc.aop;
import java.lang.reflect.Proxy;
public class JDKProxyFactory {
public static Object bind(Object origin) {
// 被代理的类必须实现某一接口,jdk会根据代理类的所有接口,创建一个具有相同实现关系的类,
//原始类和代理类之间相当于兄弟关系
// 第三个参数,要如何增强原始类,将所有增强的逻辑写在InvocationHandler的invoke中
return Proxy.newProxyInstance(origin.getClass().getClassLoader(), origin.getClass().getInterfaces(),
new JDKProxyProcessor(origin));
}
}
之所以业务层一般都有接口,是因为基本都会通过代理增强异常回滚和日志记录功能
在创建的bind()绑定方法中,因为我们不知道传进来的和返回的参数是什么,所以使
用Object(一般为原始类对象)接收。Proxy.newProxyInstance(参数1,参数2,参数3)
返回的是一个代理类,
参数1:原始类加载器(用哪个类加载器去加载代理对象);
参数2:接口(动态代理类需要实现的接口);
参数3:实现InvocationHandler标准的类的对象,动态代理方法在执行时,会调用参数3这个对象里面的invoke()方法去执行;
代理模式会对传进来的原始类Object object进行加工,获取其类加载器和接口,在JDK允许范围内,实现目标类的所有接口,然后再创建这个接口的实现(跟原始类一样),因此原始类和代理类为兄弟关系(类加载器和接口都是一样的,所以要通过第三个参数进行区分)。
我们所有要增强的功能逻辑都放在invoke()方法中
创建代理类JDKProxyProcessor.java
import java.lang.reflect.InvocationHandler;
public class JDKProxyProcessor implements InvocationHandler {
//原始类对象
private Object origin;
public JDKProxyProcessor(Object origin) {
this.origin= origin;
}
//覆盖方法
//目标类的所有方法都会被该方法增强
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果method.invoke(method, args);不执行,那么所有原始类的方法都不会执行
Object result = method.invoke(ori, args);
if(method.getName().contentEquals("add")) {
System.out.println(new Date()+" 使用参数:"+Arrays.deepToString(args)+" 执行了方法:"+method.getName()+ " 得到了: "+ result + "结果");
}
return result;
}
}
invoke三个参数:
proxy:就是代理对象,newProxyInstance方法的返回对象
method:调用的方法
args: 方法中的参数
代理接口及其实现类:
public interface Service {//接口
public void service();
public int add(int x);
}
public class Service1 implements Service{//子实现
public void service() {
System.out.println("service 1");
}
public int add(int x) {
return x+1;
}
}
public class Service2 implements Service{//子实现
public void service() {
System.out.println(" service 2");
}
public int add(int x) {
return x-1;
}
}
创建代理测试主类:ProxyMain.java
public class ProxyMain {
public static void main(String [] args) {
Service service1 = new Service1();//原始类
service1.service();
System.out.println(service1.add(3));
System.out.println("-----------------");
Service proxyService2 = (Service)JDKProxyFactory.bind(service1);//代理类
proxyService2.service();
System.out.println(proxyService2.add(3));
}
}
代理模式实现步骤总结:
- 创建JDK代理工厂类,添加bind(Object object)方法,传入原始类对象object,通过Proxy.newProxyInstance(object.类加载器, object.接口, new JDKProxyProcessor(object))返回代理类对象;
- 创建JDKProxyProcessor.java代理类,定义一个Object类型的参数,提供构造方法。添加invoke()方法,将所有要增强的逻辑写在该方法中。