代理模式为其他对象提供一种代理以控制对这个对象的访问。
代理模式
为其他对象提供一种代理以控制对这个对象的访问
让代理对象控制目标对象的访问,添加一些额外的功能。
静态代理
模式结构:三种角色
- 抽象角色:真实对象和代理对象的共同接口
- 真实角色:代理角色所代表的真实对象
- 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时,代理对象在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
//抽象角色Subject
public interface Subject {
public void doSomething();
}
//真实角色RealSubject
public class RealSubject implements Subject {
public void doSomething(){
System.out.println("一些操作");
}
}
//代理角色ProxySubject
public class ProxySubject implements Subject {
RealSubject realSubject = new RealSubject();
public void doSomething(){
System.out.println("操作前**********");
realSubject.doSomething();
System.out.println("操作后**********");
}
}
public class TestProxy {
public static void main(String[] args) {
Subject proxy = new ProxySubject();
proxy.doSomething()
}
}
输出结果
操作前**********
一些操作
操作后**********
动态代理
动态代理类的字节码在程序运行时由Java反射机制动态生成
JDK动态代理
Java动态代理类位于Java.lang.reflect包下,一般主要涉及一个类和一个接口:
- InvocationHandler接口 (java.lang.reflect.InvocationHandler)
- Proxy类 (java.lang.reflect.Proxy)
//抽象角色Subject
public interface Subject {
public void doSomething();
}
//真实角色RealSubject
public class RealSubject implements Subject {
public void doSomething(){
System.out.println("一些操作");
}
}
//代理角色ProxySubject
public class ProxySubject implements InvocationHandler {
private Object target;
public Object getProxy(Object target) {
this.target = target;
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
//要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
Object result=null;
System.out.println("操作前**********");
result=method.invoke(target, args);
System.out.println("操作后**********");
return result;
}
public class TestProxy {
public static void main(String[] args) {
ProxySubject ProxySubject = new ProxySubject();
Subject proxy = (Subject) ProxySubject.getProxy(new RealSubject());
proxy.doSomething();
}
}
输出结果
操作前**********
一些操作
操作后**********
JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了
cglib动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。
//真实角色RealSubject
public class RealSubject implements Subject {
public void doSomething(){
System.out.println("一些操作");
}
}
public class ProxySubject implements MethodInterceptor {
private Object target;
public Object getProxy(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) {
System.out.println("操作前**********");
proxy.invokeSuper(obj, args);
System.out.println("操作后**********");
return null;
public class TestProxy {
public static void main(String[] args) {
ProxySubject ProxySubject = new ProxySubject();
RealSubject proxy = (RealSubject) ProxySubject.getProxy(new RealSubject());
proxy.doSomething();
}
}
输出结果
操作前**********
一些操作
操作后**********
静态代理和动态代理区别
静态代理:由程序员或者自动生成工具生成代理类,然后进行代理类的编译和运行。在代理类、委托类运行之前,代理类已经以.class的格式存在。
动态代理:在程序运行时,由反射机制动态创建而成。
cglib和jdk代理区别
JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
cglib动态代理:利用asm开源包(java字节码操纵框架),对代理对象类的class文件加载进来,通过修改其字节码生成子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
JDK动态代理:利用用传入的接口创建一个匿名类,在该类中织入横切逻辑。