这次的博客将会介绍两种动态代理的方式,一种为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