存在意义:
- 对外部提供了提供的接口方法,而代理类在接口中实现了对真实类的附加操作行为,从而可以在不影响外部调用的情况下,进行系统扩展
- 代理模式也可以被用来区别一个对象实例的请求和实际的访问
静态代理: 需要自己生成代理类
JDK动态代理: 实现InvocationHandle接口,代理类通过反射机制生成
/**
* jdk自带动态代理类:代理类通过反射机制生成
* @title
* @description
* @since JDK1.8
*/
public class Jdkproxy implements InvocationHandler {
/**
* 这个就是我们要代理的真实对象
*/
private Object target;
/**
* 构造方法,给我们要代理的真实对象赋初值
*
* @param subject
*/
public Jdkproxy(Object target) {
this.target = target;
}
/**
* 该方法负责集中处理动态代理类上的所有方法调用。 调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param args 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在代理真实对象前我们可以添加一些自己的操作
System.out.println("我是房产中介,我jdk动态代理开始监听了!!!!!!!!!!");
// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object in = method.invoke(target, args);
// 在代理真实对象后我们也可以添加一些自己的操作
System.out.println("我是房产中介,我jdk动态代理结束监听了!!!!!!!!!!");
return in;
}
public static void main(String[] args) {
Xiaoming xm = new Xiaoming();
Jdkproxy pro = new Jdkproxy(xm);
/**
* 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
*/
House house = (House)Proxy.newProxyInstance(xm.getClass().getClassLoader(), xm.getClass().getInterfaces(), pro);
house.maiFang();
}
}
具体步骤:
- 通过实现InvocationHandler接口创建自己的调用处理器
- 通过Proxy类指定ClassLoader对象和一组interface来创建动态代理类
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型
- 通过构造函数创建动态代理类的实例,构造时调用处理器对象作为参数传入
参数说明
Object proxy: 指被代理的对象
Method method: 要调用的方法
Object[] args : 方法调用时所需要的参数
可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject
Proxy类:
是专门完成代理的操作类,可以通过此类为一个或者多个接口动态的生成实现类,此类提供了 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
参数说明:
ClassLoader loader: 类加载器
Class<?> interfaces: 得到全部接口
InvocationHandler h: 得到InvocationHandler接口的子类实例
动态代理类的字节码在程序运行时由java反射机制动态生成,无序手动编写源码.动态代理不仅简化了编程工作,提高了软件系统的可扩展性,因为java反射机制可以生成任意类型的动态代理类.java.lang.reflect包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力
CGLib动态代理: JDK动态代理机制只能代理实现了接口的类,而不能实现接口的类不能实现jdk的动态代理,Cglib是针对目标类生成指定的目标类生成一个子类,并且覆盖其中方法实现增强,但是因为采用的是继承,所以不能对final修饰的类进行代理
JDK动态代理和CGLib动态代理的区别
jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm(java字节码控制)来实现,反射机制在生成类的过程中比较高效,,而asm在生成类的过程中,比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程中低效问题).还有一点序注意: jdk动态代理的应用前提,必须是目标基于统一的接口,如果没有上述前提,jdk动态代理不能应用