代理模式:
代理模式:有代理类与委托类组成,两者有相同的接口.其中代理类主要负责为委托类预处理消息、过滤消息并把消息转发给委托类,以及事后处理消息等。
使用的目的:采用代理模式可以有效的将具体的实现与调用方进行解耦,通过面向接口进行编码完全将具体的实现隐藏在内部
静态代理的缺点:
1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法.这样就出现了大量的代码重复.造成代码冗余臃肿.
2)代理对象只能服务于一种类型的对象,如果要服务多种类型的对象.势必要为每一种对象都进行代理.
静态代理和动态代理的区别,什么场景使用?
http://blog.csdn.net/mine_song/article/details/71373305?locationNum=15&fps=1
静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类:在程序运行时,运用反射机制动态创建而成.
动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类.
静态代理与动态代理的区别:
(1)静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类.
(2)静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道.(动态代理需要在运行时因需实时创建)
(3)动态代理实现JDK的InvocationHandler接口的invoke方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过Proxy里的newProxyInstance得到代理对象.
动态代理的相关类和接口:
1.java.lang.reflect.Proxy:动态代理机制的主类,其提供了一组静态方法为一组接口(委托类)动态的生成对象和代理类
//用于获取特定代理对象所关联的调用处理器
1.1)public static InvocationHandler getInvocationHandler(Object proxy);
//用于获取关联特定类加载器和一组接口(委托类)的动态代理类的类对象
1.2)public static Class<?> getProxyClass(ClassLoader loader,Class<?> ... interface);
//用于判断特定类对象是否是一个动态代理类
1.3)public static boolean isProxyClass(Class<?> cl);
//获取特定类加载器、一组接口及调用处理器生成动态代理类的实例对象
1.4)public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);
2.java.lang.reflect.InvocationHandler:调用处理器接口,实现自定义invoke()方法,用于实现对于真正委托类的代理访问.
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
3.java.lang.ClassLoader:类加载器,将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用.Proxy类与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中.每次生成动态代理类对象时都需要指定一个类装载器对象:newProxyInstance()方法第一个参数
Java动态代理的两种实现方法:
jdk动态代理和cglib动态代理
其中jdk动态代理为interface接口代理;cglib动态代理是类代理;
动态代理的实现步骤:
1.先获取ClassLoader类加载器和Interface在虚拟机内的二进制字节码Class实例;
2.借助Proxy.newInstance(ClassLoader,Class<?>{...} clazz,InvocationHandler handler);方法构建代理类的实例,并实现InvocationHandler里面的invoke(object,args);方法来达到实现Interface接口里面需要代理的方法的目的;
3.运用反射的机制,通过第二步的代理对象,来调用Interface中相应的方法;
demo如下:
//1.拿到类加载器以及接口的Class实例
ClassLoader classLoader = IEate.class.getClassLoader();
//2.构建代理对象并实现invoke方法
IEate eat = (IEate) Proxy.newProxyInstance(classLoader, new Class[]{IEate.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("eat")) {
return args[0];
}
return method.invoke(proxy, args);
}
});
//3.调用第二步的代理对象
System.out.println(eat.eat("蜀国"));
文章参考:
1. java动态代理原理及解析2. Java动态代理的两种实现方法