1、JDK动态代理
JDK动态代理通过JDK的Proxy类实现,JDK提供的动态代理需要实现InvocationHandler接口的invoke方法.此方法为整个代理的入口。方法签名为
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
第一个参数是代理对象,第二个参数是目标方法,第三个参数是目标方法参数
public class ProxyHandler implements InvocationHandler{
Object target;
public ProxyHandler(Object target) {
this.target=target;
}
public void before(String param) throws Throwable{
if(!param.equals("magicalwolf"))
throw new IllegalArgumentException();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before((String)args[0]);
return method.invoke(target, args);
}
}
之后通过Proxy类的newProxyInstance方法创建代理对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
第一个参数是目标对象的类加载器,第二个参数是目标类实现的接口,第三个参数是处理器InvocationHandler
public class Main {
public static void main(String[] args) {
Subject target=new RealSubject();
Subject proxy=(Subject)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new ProxyHandler(target));
proxy.request("magicalwolf");
proxy.request("hello");
}
}
可以看到使用JDK提供的动态代理无需为每个对象都实现一个代理类,通过处理器,可以对不同的对象生成代理类。
newProxyInstance方法通过接口生成子类,然后通过反射构建实例
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
注:但是JDK的动态代理是通过代理接口实现的,如果对象没有实现接口,那就无能为力了。
Ciglib动态代理
CGLIB是一个强大的高性能的代码生成包,在运行时动态生成字节码并生成新类。
CGLIB提供了MethodInterceptor接口,当调用目标方法时被回调,类似于InvocationHandler.
public class RequestInterceptor implements MethodInterceptor{
public void before(String param) throws Throwable{
if(!param.equals("magicalwolf"))
throw new IllegalArgumentException();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
before((String)args[0]);
return proxy.invokeSuper(obj, args);//调用父类的方法
}
}
生成代理类
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer(); //字节码增强器
enhancer.setSuperclass(RealSubject.class); //代理类
enhancer.setCallback(new RequestInterceptor());//回掉方法
Subject proxy=(Subject) enhancer.create();
proxy.request("magicalwolf");
proxy.request("hello");
}
}
可以看到,CGLIB是通过动态生成目标类的子类,在子类中设置拦截逻辑,来进行动态代理。因此目标类的方法不能被final修饰。
总结
jdk动态代理通过JDK的proxy类实现,要求被代理类必须提供接口,原理是通过反射机制,生成接口新的实现类。
cglib动态代理通过cglib字节码增强器实现,原理是生成被代理类的子类,因此方法不能用final修饰。