说起动态代理,大家可能都很熟悉,个人自认为动态代理最大的优势就是对原对象无任何侵入的情况下,可以对该对象中的某一方法进行扩展。体现最直接就是Spring中当的Aop了,还有Mybatis中的interface。
动态代理可以分为两种:
1.JDK动态代理,在运行时,jvm动态的生成代理类的class字节码数据,然后从字节码数据中创建代理对象的Class实例,拿到Class实例后通过Java反射生成代理类。这个二进制文件可以是本地,也可以是网络的只要能被java验证通过就可以创建成新的对象。
具体示例如下:
父类接口:
package com.example.demo.proxy.jdk;
public interface Person {
void doing();
}
子类:
package com.example.demo.proxy.jdk;
public class Kevin implements Person {
@Override
public void doing() {
System.out.println("I like basketball.");
}
}
代理类:
package com.example.demo.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class KevinProxy implements InvocationHandler{
private Object target;
public KevinProxy(Object target){
this.target= target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("do before.");
Object result= method.invoke(target,args);
System.out.println("do after.");
return result;
}
}
测试:
package com.example.demo.proxy.jdk;
import java.lang.reflect.Proxy;
public class Test {
public static void test(){
Person person= (Person) Proxy.newProxyInstance(Kevin.class.getClassLoader(),Kevin.class.getInterfaces(),new KevinProxy(new Kevin()));
person.doing();
System.out.println(person.getClass().getName());
}
public static void main(String[] args) {
test();
}
}
2.CGLIB动态代理是基于java开源字节码生成框架ASM,它可以以二进制的形式修改或者生成新的类,在运行时动态生成一个要代理类的子类,因为是子类所以final方法不能被重写。
代码如下:
接口:
package com.example.demo.proxy.cglib;
public class Lisa {
public void doing(){
System.out.println("lisa like coffee");
}
}
代理类:
package com.example.demo.proxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class LisaProxy implements MethodInterceptor {
private Enhancer enhancer= new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("doing before");
Object result= methodProxy.invokeSuper(o,objects);
System.out.println("doing end");
return result;
}
}
测试:
package com.example.demo.proxy.cglib;
public class Test {
public static void main(String[] args) {
Lisa lisa= (Lisa) new LisaProxy().getProxy(Lisa.class);
lisa.doing();
System.out.println(lisa.getClass().getName());
}
}
网友评论