这次的博客将会介绍两种动态代理的方式,一种为jdk动态代理,一种为cglib动态代理,在代码方面将会使用最少的代码来完成,类会尽量的少,帮助大家理解。
先讲一下这两种代理方式的主要区别,jdk动态代理要求代理的类必须要有实现的接口,而cglib是通过创建子类进行代理,不需要实现接口,具体操作马上介绍。
首先创建一个接口、一个类实现接口:
public interface Action { void action(); } public class Person implements Action{ @Override public void action() { System.out.println("切面"); } }
下面创建一个处理器类,实现jdk的InvocationHandler接口,这个处理器类用来对代理对象进行处理:
public class PersonInvocationHandler implements InvocationHandler{ private Person p; public PersonInvocationHandler (Person p){ this.p = p; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("前置事件"); method.invoke(p, args); System.out.println("后置事件"); return null; } }
在这个类中的参数介绍:
private Person p:需要进行Aop的对象,你可以改为任何想要的形式,比如private Object obj;或者你自己现在
创建一个类,然后写入。
Object proxy:基本不会用到,是jdk动态代理生成的对象,之后马上介绍,可以忽略。
Method method:jdk动态代理生成的代理对象所调用的方法。
Object args[]:上面method的参数。
这样看起来,我们的对象和PersonInvocationHandler还完全没有联系起来,接下来,我们将两者进行关联,创建一个Test测试类,内部只有一个main方法:
public class Test { public static void main(String[] args) { Person p = new Person(); InvocationHandler h = new PersonInvocationHandler(p); Action proxy = (Action) Proxy.newProxyInstance(p.getClass().getClassLoader(), p.getClass().getInterfaces(), h); proxy.action(); } }
首先创建一个Person类的对象p,我们要对p的action方法进行Aop,那么便需要与之前的PersonInvocationHandler联系起来,我们在创建PersonInvocationHandler的时候指定了构造函数,那么按照构造函数创建一个对象h,此h对象便是处理器。
接着创建一个代理对象,该对象通过java.lang.reflect.Proxy类的newProxyInstance方法创建,参数三个,分别为:
ClassLoader:类加载器,使用p.getClass().getClassLoader()即可。
Class<?>[]:jdk创建的代理对象需要实现的接口,数组形式。
InvocationHandler:处理器,创建的代理对象的任何方法都会经过该处理器,aop的关键
我们通过Proxy.newProxyInstance方法创建的proxy对象在执行方法时,全部会通过PersonInvocationHandler中的invoke方法,在上面没有介绍的invoke方法中的Object proxy参数即为此处创建的proxy对象。
这样一来我们就实现了一个简单的动态代理,如果你要处理更复杂业务,只需要添加相应的业务代码到InvocationHandler中的invoke方法中便能实现。
虽然jdk动态代理已经很好用了,但我们有时候没有实现接口该怎么办呢,此时就需要请出cglib动态代理了。
cglib动态代理不再是创建实现了指定借口的对象了,而是创建继承了指定类的对象:
public class Test { public static void main(String[] args) { Enhancer en = new Enhancer(); en.setSuperclass(Person.class); en.setCallback( new CGlibProxy() ); Person p = (Person) en.create(); p.action(); } }Enhancer翻译过来即为增强器,相当于jdk动态代理中的Proxy类,同样是用于创建代理对象,
setSuperclass(Class<?> clazz)用于指定需要继承的类。
setCallback(Callback callback)用于指定处理器。
在cglib中也有处理器,不过名字却叫做拦截器了,如下所示,实现了MethodInterceptor接口:
public class CGlibProxy implements MethodInterceptor { @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("前置事件"); Object result = methodProxy.invokeSuper(object, args); System.out.println("后置事件"); return result; } }内部有一个需要实现的方法intercept