Proxy代理模式

2016/04/27 DesignPatterns

代理模式为其他对象提供一种代理以控制对这个对象的访问。

代理模式

为其他对象提供一种代理以控制对这个对象的访问

让代理对象控制目标对象的访问,添加一些额外的功能。

静态代理

模式结构:三种角色

  • 抽象角色:真实对象和代理对象的共同接口
  • 真实角色:代理角色所代表的真实对象
  • 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时,代理对象在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
//抽象角色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动态代理:利用用传入的接口创建一个匿名类,在该类中织入横切逻辑。

Search

    Post Directory