动态代理简介:
java代理有jdk动态代理、cglib代理,这里只说下jdk动态代理,jdk动态代理主要使用的是java反射机制(既java.lang.reflect包)
动态代理原理:
原理是(歌手、经纪人做例子):
建立一个公共的接口,比如:歌手public interface Singer;
用具体的类实现接口,比如:周杰伦,他是歌手所以实现Singer这个类,class MySingerimplements Singer;
建立代理类,这里也就是经纪人,他需要实现InvocationHandler类,并重写invoke方法;
这样当有什么事情,要找周杰伦(具体类)的时候,就必须先到经纪人(代理类)那里处理,代理人在决定要不要与你见面(该方法要不要执行);
Proxy类:
动态代理:程序运行时,使用JDK提供工具类(Proxy),动态创建一个类,此类一般用于代理。
代理:你 -- 代理(增强) -- 厂商.
代理类: 目标类:被代理的.
动态代理使用前提:必须有接口.
Object proxyObj= Proxy.newProxyInstance(参数1,参数2,参数3);
参数1:ClassLoader,负责将动态创建类,加载到内存。当前类.class.getClassLoader();
参数2:Class[] interfaces ,代理类需要实现的所有接口(确定方法),被代理类实例.getClass().getInterfaces();
参数3:InvocationHandler, 请求处理类,代理类不具有任何功能,代理类的每一个方法执行时,调用处理类invoke方法。
voke(Object proxy ,Method ,Object[] args)
参数1:代理实例
参数2:当前执行的方法
参数3:方法实际参数。
废话不说先看一段代码:
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Daili {
@Test
public void Demo01() {
List<String> list = new ArrayList<>();
list.add("a");
System.out.println(list);
List<String> list2 = Collections.unmodifiableList(list);
list2.add("b"); // 错误提示,不允许操作 因为Collections工具类使得list2变得不能增删改了,只能查询
System.out.println(list2);
}
}
输出的结果:
结果是有异常的,因为Collections工具类已经把list变成了list2且list2只能查询不能增删改了.
接下来我们用代理自己手动实现这个功能,也就是我们自己增强功能:
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Daili {
@Test
public void Demo02() {
List<String> list = new ArrayList<>();
list.add("a");
List<String> list2 = MyCollections.unmodifiableList(list);
list2.add("b");
System.out.println(list2.size());
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
public class MyCollections {
public static List<String> unmodifiableList(final List<String> list) {
// list 增删改查功能都有,这是目标类 我们现在进行不能增
// 参数1:ClassLoader ,动态代理需要一个类加载器
ClassLoader classLoader = MyCollections.class.getClassLoader();
// 参数2:Class[] interfaces 需要与目标类接口保持一致
Class[] interfaces = list.getClass().getInterfaces();
//proxyList 希望不能进行增删改,只能查询 (代理类)
List<String> proxyList = (List<String>) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 处理(增强) -- 不允许添加
String methodName = method.getName();
if ("add".equals(methodName)) {
throw new UnsupportedOperationException("不允许添加");
}
return method.invoke(list,args);
}
});
return proxyList;
}
}
输出结果: