学习准备2

23种设计模式

8> 代理模式

这篇文章写的较简洁易懂:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

分为静态代理、动态代理。动态代理又有两种实现:JDK动态代理、cglib动态代理

静态代理:

interface Subject {
    void request();
}

class RealSubject implements Subject {
    public void request(){
        System.out.println("RealSubject");
    }
}

class Proxy implements Subject {
    private Subject subject;

    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("begin");
        subject.request();
        System.out.println("end");
    }
}

public class ProxyTest {
    public static void main(String args[]) {
        RealSubject subject = new RealSubject();
        Proxy p = new Proxy(subject);
        p.request();
    }
}

静态代理实现中,一个委托类对应一个代理类,代理类在编译期间就已经确定。

* 动态代理(JDK动态代理)

interface Subject {
    void request();
}

class RealSubject implements Subject {
    public void request(){
        System.out.println("RealSubject");
    }
}

public class DynamicProxy implements InvocationHandler {

 

private Object obj;

 

public DynamicProxy() {

 

}

 

public DynamicProxy(Object obj) {

this.obj = obj;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

 

System.out.println("before calling method");

method.invoke(obj, args);

System.out.println("after calling method");

return null;

}

 

客户端

public class Client {

 

public static void main(String[] args) {

Subject sub = new SubjectImpl();

//这里指定被代理类  

InvocationHandler ih = new DynamicProxy(sub);

Class<?> cla = sub.getClass();

 

   //以下是一次性生成代理 

Subject subject = (Subject) Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), ih);

 

  //这里可以通过运行结果证明subject是Proxy的一个实例,这个实例实现了Subject接口  

        System.out.println(subject instanceof Proxy);  

        

        System.out.println("subject的Class类是:"+subject.getClass().toString());  

        

        System.out.print("subject中的属性有:");  

        

        Field[] field = subject.getClass().getDeclaredFields();

        for(Field s:field){

        System.out.println(s.getName());

        }

        

        System.out.print(" "+"subject中的方法有:");  

        

        Method[] method=subject.getClass().getDeclaredMethods();  

          

        for(Method m:method){  

            System.out.print(m.getName()+", ");  

        }  

          

        System.out.println(" "+"subject的父类是:"+subject.getClass().getSuperclass());  

          

        System.out.print(" "+"subject实现的接口是:");  

          

        Class<?>[] interfaces=subject.getClass().getInterfaces();  

          

        for(Class<?> i:interfaces){  

            System.out.print(i.getName()+", ");  

        }  

  

        System.out.println(" "+"运行结果为:");  

        subject.method();  

    }  

}

JDK动态代理中包含一个类和一个接口: 
InvocationHandler接口: 
public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 

参数说明: 
Object proxy:指被代理的对象。 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数 

可以将InvocationHandler接口的子类想象成一个代理的最终操作类

Proxy类: 
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: 
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
InvocationHandler h) 
                               throws IllegalArgumentException 
参数说明: 
ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例 

Ps:类加载器 
在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器; 
Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的; 
Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jrelibext目录中的类; 
AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。 

动态代理 
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 

 

动态代理(cglib动态代理)

 

但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。 

Cglib动态代理 
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 

示例:

public class CglibProxy implements MethodInterceptor{

 

private Enhancer enhancer = new Enhancer();

 

public Object getProxy(Class clazz){

//设置需要创建子类的类  

enhancer.setSuperclass(clazz);

enhancer.setCallback(this);

//通过字节码技术动态创建子类实例  

Object obj = enhancer.create();

return obj;

}

@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

System.out.println("前置代理");

Object result = proxy.invokeSuper(obj, args);

System.out.println("后置代理");

return result;

}

}

测试类

public class CglibTest {

 

public static void main(String[] args) {

CglibProxy proxy = new CglibProxy();

//通过生成子类的方式创建代理类 

SubjectImpl sub = (SubjectImpl) proxy.getProxy(SubjectImpl.class);

sub.method();

}

}

原文地址:https://www.cnblogs.com/-wyl/p/7161277.html