java代理
为什么使用代理
代理分类
注:代理一定要实现被代理类中的方法,于是我们经常会看见把代理和被代理中的方法抽象为一个借口,增加了一个约束。
准备工作
接口:
public interface ProxyInterface {
void doAction();
}
实现类:
public class Action implements ProxyInterface {
@Override
public void doAction() {
System.out.println("do action ...");
}
public void test(){
System.out.println("action test ...");
}
@TestAnnotation
public final String test1(){
System.out.println("action test string ...");
return "hello cglib";
}
@TestAnnotation
public final String test1(String s){
System.out.println(s);
System.out.println("action test string ...");
return "hello cglib";
}
}
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation {
}
静态代理
静态需实现接口,或者继承父类,保证与呗代理类有相同的方法签名。
定义代理类,继承接口:
public class ActionProxy implements ProxyInterface {
private ProxyInterface proxy;
public ActionProxy(ProxyInterface proxy){
this.proxy = proxy;
}
@Override
public void doAction() {
System.out.println("before action ...");
proxy.doAction();
System.out.println("after action ...");
}
}
public class Exec {
public static void main(String[] args) {
Action action = new Action();
ActionProxy actionProxy = new ActionProxy(action);
actionProxy.doAction();
}
}
run result:
before action ...
do action ...
after action ...
动态代理
jdk动态代理
jdk动态代理主要用到反射包中的两个类:
java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler
public class MyInvocationHandler<T> implements InvocationHandler {
/**
* 目标对象
*/
private T target;
public MyInvocationHandler(){
}
public MyInvocationHandler(T target){
this.target = target;
}
/**
* 获取代理对象
* @param <T>
* @return
*/
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before action do do do ....");
return method.invoke(target,args);
}
}
创建代理类有以下几种实现方式:
public class Exec {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 保存字节码
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Action action = new Action();
MyInvocationHandler handler = new MyInvocationHandler<ProxyInterface>(action);
// 分步
Class<?> proxyClass = Proxy.getProxyClass(Action.class.getClassLoader(), Action.class.getInterfaces());
// Class<?> proxyClass = Proxy.getProxyClass(Action.class.getClassLoader(), new Class<?>[]{ProxyInterface.class});
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
ProxyInterface o = (ProxyInterface) constructor.newInstance(handler);
o.doAction();
// 直接创建代理类
ProxyInterface jdkProxy = (ProxyInterface) Proxy.newProxyInstance(Action.class.getClassLoader(), Action.class.getInterfaces(), handler);
jdkProxy.doAction();
// java8 lambam写法
ProxyInterface jdkProxy1 = (ProxyInterface) Proxy.newProxyInstance(
Action.class.getClassLoader(),
Action.class.getInterfaces(),
(proxy, method, params) -> {
System.out.println("before...");
Object invoke = method.invoke(action, params);
System.out.println("after...");
return invoke;
}
);
jdkProxy1.doAction();
ProxyInterface proxy = new MyInvocationHandler<ProxyInterface>(action).getProxy();
proxy.doAction();
}
}
cglib动态代理
简述
并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码。
cglib动态代理需要有回调方法,继承自Callback接口,cglib 实现了6种回调方法(callback):
- FixedValue
- InvocationHandler
- LazyLoader
- MethodInterceptor
- Dispatcher
- NoOp
代理实现:
/**
* 查找A上的所有非final 的public类型的方法定义;
* 将这些方法的定义转换成字节码;
* 将组成的字节码转换成相应的代理的class对象;
* 实现 MethodInterceptor接口,用来处理 对代理类上所有方法的请求(这个接口和JDK动态代理InvocationHandler的功能和角色是一样的)
*/
public class Exec {
public static void main(String[] args) {
Action action = new Action();
CglibInterceptor cglibInterceptor = new CglibInterceptor();
// cglib加强器,用来创建动态代理
Enhancer enhancer = new Enhancer();
// 设置要动态代理的类
enhancer.setSuperclass(Action.class);
// 设置回调,相当于所有方法都要回调
enhancer.setCallback(cglibInterceptor);
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
System.out.println("before proxy");
// method.invoke(action,objects);
// 代理类的父类
method.invoke(proxy.getClass().getSuperclass().newInstance(),args);
System.out.println("after proxy");
return null;
}
});
// 拦截器过滤
CallbackHelper callbackHelper = new CallbackHelper(action.getClass(), null) {
@Override
protected Object getCallback(Method method) {
// if(method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) {
// return cglibInterceptor;
// }
Annotation annotation = method.getAnnotation(TestAnnotation.class);
if(annotation != null){
return cglibInterceptor;
}
return NoOp.INSTANCE;
}
};
enhancer.setCallbackFilter(callbackHelper);
enhancer.setCallbacks(callbackHelper.getCallbacks());
Action proxy = (Action) enhancer.create();
// proxy.doAction();
proxy.test1();
}
}
源码浅析:
Enhancer.createHelper()
private Object createHelper() {
this.preValidate();
// 一级缓存使用的key
Object key = KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter == ALL_ZERO ? null : new WeakCacheKey(this.filter), this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
CallbackHelper中用到Enhancer.getMethods()
private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) {
ReflectUtils.addAllMethods(superclass, methods);
List target = interfaceMethods != null ? interfaceMethods : methods;
if (interfaces != null) {
for(int i = 0; i < interfaces.length; ++i) {
if (interfaces[i] != Factory.class) {
ReflectUtils.addAllMethods(interfaces[i], target);
}
}
}
if (interfaceMethods != null) {
if (forcePublic != null) {
forcePublic.addAll(MethodWrapper.createSet(interfaceMethods));
}
methods.addAll(interfaceMethods);
}
// 过滤static修饰的方法
CollectionUtils.filter(methods, new RejectModifierPredicate(8));
// 过滤不可见方法,private/与目标类不在同一个包中的方法
CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true));
// 过滤重复方法
CollectionUtils.filter(methods, new DuplicatesPredicate());
// 过滤final修饰方法
CollectionUtils.filter(methods, new RejectModifierPredicate(16));
}
java.lang.reflect.Modifier的静态属性对应如下:
- PUBLIC: 1
- PRIVATE: 2
- PROTECTED: 4
- STATIC: 8
- FINAL: 16
- SYNCHRONIZED: 32
- VOLATILE: 64
- TRANSIENT: 128
- NATIVE: 256
- INTERFACE: 512
- ABSTRACT: 1024
- STRICT: 2048
Enhancer会过滤final/static/private修饰的/重复的方法/默认修饰符且与目标类不在同一个包中的方法。
CGLIB动态代理与JDK动态区别
- java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
- cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。 因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。