本文主要讲的是如何使用JDK动态代理实现简单的AOP。AOP是啥?若是你想在某些方法执行先后插入一些通用的处理,你能够考虑AOP。java
JDK中提供了一个Proxy
类用于建立动态代理对象的静态方法,若是在程序中为一个或多个接口动态地生成实现类,就能够使用Proxy来建立动态代理类。 Proxy
提供了下面的方法来建立动态代理实例:ide
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)测试
该代理对象的实现类实现了interfaces所指定的系列接口,执行代理对象的每一个方法时都会被替换执行InvocationHandler
对象的invoke
方法this
InvocationHandler是一个接口,在建立动态代理实例的时候须要把一个InvocationHandler
的实现类传进去,那么执行代理对象的每一个方法时就会被替换成执行InvocationHandler实现类中的invoke方法,至于这个invoke方法要怎么实现,就由用户本身决定。spa
在java.lang.reflect.Method
包中有一个方法代理
public Object invoke(Object obj, Object... args)code
该方法能够实现对象方法的调用,它是Method
类的实例方法,该方法中的参数obj
是调用方法的对象,args
是用于方法调用的参数。对象
Pig接口,就定义了两个方法接口
public interface Pig {
void info();
void run();
}
复制代码
Pig的实现类,咱们要作的就是在这两个方法执行的先后插入本身一些额外的操做get
public class FatPig implements Pig {
@Override
public void info() {
System.out.println("我是一头小肥猪!");
}
@Override
public void run() {
System.out.println("我要跑步啦!");
}
}
复制代码
LogUtils,须要在代理对象方法执行先后调用的方法
public class LogUtils {
public void before() {
System.out.println("==== 方法开始执行 ====");
}
public void after() {
System.out.println("==== 方法执行结束 ====");
}
}
复制代码
PigInvocationHandler,该类实现了InvocationHandler接口。咱们定义了一个Object类型的实例变量,由于咱们须要在invoke方法中调用被代理对象的实现类的对应的方法。在invoke方法中,有两个关键的参数:method
表明正在执行的方法,args
表明调用目标方法时传入的实参。而后咱们就能够在执行代理对象的方法先后自由插入本身的方法了。
public class PigInvocationHandler implements InvocationHandler {
// 须要被代理的对象
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 执行动态代理对象的全部方法时,都会被替换成执行以下的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
LogUtils logUtils = new LogUtils();
// 执行logUtils对象中的before方法
logUtils.before();
// 以target做为主调来执行method方法
Object result = method.invoke(target, args);
// 执行logUtils对象中的after方法
logUtils.after();
return result;
}
}
复制代码
测试类
public class MyProxyFactory {
// 为指定的target生成动态代理对象
public static Object getProxy(Object target) {
PigInvocationHandler handler = new PigInvocationHandler();
// 为handler设置target对象
handler.setTarget(target);
// 建立并返回一个动态代理
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
public static void main(String[] args) throws Exception {
// 建立一个原始的FatPig对象,做为target
Pig target = new FatPig();
// 以指定的target来建立动态代理对象
Pig pig = (Pig) MyProxyFactory.getProxy(target);
pig.info();
pig.run();
}
}
复制代码
运行结果:
==== 方法开始执行 ====
我是一头小肥猪!
==== 方法执行结束 ====
==== 方法开始执行 ====
我要跑步啦!
==== 方法执行结束 ====
上面实现了简单的AOP功能,咱们能够在invoke方法里面加上更多的判断,使得功能更增强大,例如能够根据method参数指定某些方法先后执行特殊的处理。