java代理模式解读

1.为什么需要代理?  

一个明显有一套房产要出售,他很忙没有时间,于是找了个亲戚(二哥)来帮他谈卖房子的事,二哥就是他的代理,这个二哥没有消息发布渠道,于是找到房产中介,一个业务员具体负责这套房产的推销工作,有事直接与二哥联系,那么业务员就是二哥的代理。 所有的人物有共同的行为:卖房。

代理一般是客户因为某些原因不便直接出面,比如隐私,或者是没有时间或者某一方面的专业知识,所以找代理来解决问题。

具体到软件行业,主要有两点,一个是安全问题,不希望客户直接接触到真实的业务对象,另一个就是性能问题,比如hibernate的延迟加载,稍后具体解释。 

  
2.代理对象的组成  
        抽象的接口:是真是对象与代理对象的共同接口,该接口规定了真实对象与代理对象的共同行为  
        代理对象:具有与真实对象相同的行为,其包含了真实对象的一个引用,可以通过该引用操作真实对象,这些客户端并不知道该引用,另外,代理对象也可以在真实对象行为基础上对真实对象的行为进行一些包装,例如AOP原理就是基于代理,但是他是用到动态代理,明天将会整理一下动态代理的资料.  
        真实对象:最终要引用的对象,一切都是在围绕真实对象进行封装 

 3.代码

接口

public interface Subject {     
    
    public void doSth();     
         
}
真是对象

public class RealSubject implements Subject {     
    
    @Override    
    public void doSth() {     
        System.out.println("realsubject--?request");     
    }     
}
代理对象

public class ProxySubject extends Subject {     
    
    private RealSubject subject = null;     
         
    @Override    
    public void doSth() {     
        before();     
        if(null == subject) {     
            subject = new RealSubject();     
        }     
        subject.doSth();     
        after();     
    }     
    
    public void before() {     
        System.out.println("before");     
    }     
         
    public void after() {     
        System.out.println("after");     
    }     
}
客户端代码

Java代码    
public class Client {     
    
    public static void main(String[] args) {     
        Subject proxy = new ProxySubject();     
        proxy.doSth();     
    }     
}    
  
public class Client {  
  
    public static void main(String[] args) {  
        Subject proxy = new ProxySubject();  
        proxy.doSth();  
    }  
}
JDK动态代理

代理类的字节码将在运行时生成并在如当前的classloader。

相对于静态类的优势:

1. 不需要为真实对象写一个形式上一样的封装类。 静态代理接口变动,维护麻烦。 

2. 运行时指定代理类的执行逻辑。 提升灵活性。

代理类的内部逻辑由handler决定。

InvocationHandler 代理对象的引用句柄实现这个接口。 每一个代理实例有一个引用句柄和它关联,当一个方法被代理实例调用,这个方法调用编译并分发到它的调用句柄的方法上。

实现了InvocationHandler接口的  
 Object invoke(Object proxy, Method method, Object[] args)  
  
Proxy 代理类  
Method 调用的方法  
Args  调用方法的参数  
的方法的类可以作为InvocationHandler类的参数来构建Proxy类的实例  

static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)  
loader - the class loader to define the proxy class in   
interfaces - the list of interfaces for the proxy class to implement   
h - the invocation handler to dispatch method invocations to   
  
Example:  
  ConnectionWrapper(Connection con) {  
    Class[] interfaces = {  
        java.sql.Connection.class};  
    this.connection = (Connection) Proxy.newProxyInstance(  
        con.getClass().getClassLoader(),  
        interfaces, this);  
    m_originConnection = con;  
  }
作用说明:  
当调用被代理的类(Connection)的实例的方法时系统将转到包含代理类(Proxy)的InvocationHandler的invoke方法中去执行相应代码。  
这样就可以在不修改代码的前提下为已经存在的类来添加新的功能。

java 动态代理范例 InvocationHandler与Proxy,拦截与代理 

JDK1.2以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个拦截处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行业务方法,在业务方法被调用的同时,执行处理器会被自动调用.        

Java动态代理只能对实现了接口的类生成代理,不能针对类。其实现主要是通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现.

  1.  接口类源代码:  
  2. public interface HelloWorld {     
  3.     public void sayHelloWorld();     
  4. }    
  5.   
  6. 实现类源代码:  
  7. public class HelloWorldImpl implements HelloWorld {     
  8.     public void sayHelloWorld() {     
  9.         System.out.println("Hello World!");     
  10.     }     
  11. }    
  12.   
  13. 拦截器源代码:  
  14. public class HelloWorldHandler implements InvocationHandler {     
  15.     //目标对象    
  16.     private Object targetObject;     
  17.          
  18.     public HelloWorldHandler(Object targetObject){     
  19.         this.targetObject = targetObject;     
  20.     }     
  21.          
  22.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {     
  23.         System.out.println("before invoked ...");     
  24.     
  25.         Object result = method.invoke(this.targetObject, args);     
  26.     
  27.         System.out.println("after invoked ... ");     
  28.              
  29.         return result;     
  30.     }     
  31. }    
  32.   
  33. 测试代码:  
  34. public class HelloWorldTest {     
  35.     public static void main(String[] args) {     
  36.         //业务对象    
  37.         HelloWorld obj = new HelloWorldImpl();     
  38.              
  39.         //拦截器对象    
  40.         HelloWorldHandler handler = new HelloWorldHandler(obj);     
  41.              
  42.         //返回业务对象的代理对象    
  43.         HelloWorld proxy = (HelloWorld)Proxy.newProxyInstance(     
  44.                 obj.getClass().getClassLoader(),      
  45.                 obj.getClass().getInterfaces(),      
  46.                 handler);     
  47.              
  48.         //通过代理对象执行业务对象的方法    
  49.         proxy.sayHelloWorld();     
  50.     }     
  51. }   



你可能感兴趣的:(java代理模式解读)