使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
public interface Work {
void doWork();
}
//被代理类
public class NetWork implements Work{
@Override
public void doWork() {
System.out.println("run NetWork");
}
}
//代理类
public class WorkProxy implements Work{
private Work work;
public WorkProxy(Work work){
this.work = work;
}
@Override
public void doWork() {
System.out.println("run WorkProxy");
work.doWork();
}
}
public static void main(String[] args) {
NetWork netWork = new NetWork();
WorkProxy workProxy = new WorkProxy(netWork);
workProxy.doWork();
//run WorkProxy
//run do Work
}
静态代理的缺点
① 代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。
② 每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
1、调试
2、远程方法调用
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
通过Proxy.newProxyInstance()实现
问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。
(通过InvocationHandler接口的实现类及其方法invoke())
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
Proxy.newProxyInstance(目标对象的类加载器,目标对象的接口,InvocationHandler调用代理对象时做的事情 )
public interface Work {
void doWork();
}
public class NetWork implements Work{
@Override
public void doWork() {
System.out.println("run NetWork");
}
}
public static void main(String[] args) {
NetWork netWork = new NetWork();
Work proxy = proxy(netWork);
proxy.doWork();
//run Proxy
//run NetWork
}
//进行Proxy动态代理,返回代理对象
public static<T> T proxy(T obj){
Class clazz = obj.getClass();
//newProxyInstance方法,返回的就是代理对象
T proxtObj = (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
//proxy代理对象
//method调用的方法
//args方法的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("run Proxy");
return method.invoke(obj, args);
}
});
return proxtObj;
}
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
1、引入cglib的jar文件和asm的jar文件到工程
2、引入功能包后,就可以在内存中动态的创建子类
3、被代理类不可以使用final,否则报错
4、被代理的方法,不可以使用final或static修饰
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.10</version>
</dependency>
public static void main(String[] args) {
NetWork netWork = new NetWork();
NetWork cglibProxy = cglib(netWork);
cglibProxy.doWork();
//run Cglib Proxy
//run NetWork
}
public static<T> T cglib(T obj){
//创建一个增强器
Enhancer enhancer = new Enhancer();
//设置父类,也就是被代理类
enhancer.setSuperclass(obj.getClass());
//设置方法的处理扩展
enhancer.setCallback(new MethodInterceptor() {
//o代理对象本身
//method被代理对象的方法
//objects方法的参数
//methodProxy方法的代理
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("run Cglib Proxy");
return method.invoke(obj,objects);
}
});
//获取一个代理对象
return (T) enhancer.create();
}