慕课网,模式的秘密——代理模式,https://www.imooc.com/video/4877
代理模式:为其他对象提供一种代理,以控制对这个对象的访问。代理对象起到中介的作用,可以去掉功能或是增加额外服务。
几种代理模式
- 远程代理,类似客户端-服务器,为不同地理的对象,提供局域网代表对象。
- 虚拟代理:根据需要,将资源消耗很大的对象进行延迟,真正需要的时候才创建。
- 保护代理:控制对一个对象的访问权限。
- 智能引用代理:提供对目标对象额外的功能。
代理的两种实现方式
- 静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或继承相同的抽象类
- 动态代理
一、静态代理
可以由聚合或继承来实现,聚合比继承更好,可以避免类的膨胀。
二、动态代理
2.1 jdk动态代理
要求被代理对象的类必须实现某个接口,实现步骤
(1)实现InvocationHandler类,增加目标对象的功能。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 定义处理器实现类
* 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象
*/
public class InvocationHandlerImpl implements InvocationHandler{
/**
* 这个就是我们要代理的真实对象
*/
private Object target;
/**
* 构造方法,给我们要代理的真实对象赋初值
*
* @param target
*/
public InvocationHandlerImpl(Object target){
this.target = target;
}
/**
* 该方法负责集中处理动态代理类上的所有方法调用。
* 调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
*
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param args 调用参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before invoking method operation");
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object returnValue = method.invoke(target, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after invoking method operation");
return returnValue;
}
// 也可以同时提供生成代理类的对象
public Object CreatProxyedObject(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
(2)生成目标对象的代理类,调用目标对象方法,执行增加的功能代码。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* 动态代理演示
*/
public class DynamicProxyDemonstration{
public static void main(String[] args){
//代理的真实对象
Subject realSubject = new RealSubject();
/**
* InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
* 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
* 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
*/
InvocationHandler handler = new InvocationHandlerImpl(realSubject);
ClassLoader loader = realSubject.getClass().getClassLoader();
Class[] interfaces = realSubject.getClass().getInterfaces();
/**
* 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
*/
Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
System.out.println("动态代理对象的类型:"+subject.getClass().getName());
String hello = subject.SayHello("test jdk proxy");
System.out.println(hello);
}
}
2.2 cglib动态代理
final修饰的类,不能使用cglib动态代理
(1)实现MethodInterceptor类,增加目标对象的功能。
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
/**
* 为指定class的类创建代理类
*/
public Object getObject(Class clazz){
//设置创建子类的类,即为哪个类创建子类,作为代理对象
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 拦截所有目标类的方法
* obj 目标类的对象
* method 目标方法的反射对象
* args 方法的参数
* proxy 代理类的实例
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy){
System.out.println("before method invoked");
//代理类调用父类的方法
proxy.invokeSuper(obj, args);
System.out.println("after method invoke");
}
}
(2)生成目标对象的代理类,调用目标对象方法,执行增加的功能代码。
public class Client{
public static class main(String[] args){
CglibProxy proxy = new CglibProxy();
Train train = (Train)proxy.getProxy(Train.class);
train.move();
}
}
a