zoukankan      html  css  js  c++  java
  • java静态代理与动态代理

    原文链接:http://www.orlion.ga/207/

    一、代理模式

        代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象。由代理对象来控制具体对象的引用。

        代理模式涉及到的角色:

            抽象主题角色:声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替。

    1.     代理主题角色:含有真实主题的引用,从而可以在任何时候操作真实主题,代理主题功过提供和真实主题相同的接口,使它可以随时代替真实主题。代理主题通过持有真实主题的引用,不但可以控制真实主题的创建或删除,可以在真实主题被调用前进行拦截,或在调用后进行某些操作。

         真实代理对象:定义了代理角色所代表的具体对象。

        (设计模式是通用的)

        按照代理创建的时期代理类可以分成两种:

            静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在        了。

            动态代理:在程序运行时,运用反射机制动态创建而成。

        

    二、静态代理

        Talk is cheap,show me the code

        首先定义个酒厂的接口:

        WineFactory.java

        package ml.orlion.proxy;    
        
        public interface WineFactory {
        
        	public void sell();
        }

        然后再定义一个酒厂类实现这个接口:

        WineFactoryImpl.java

        package ml.orlion.proxy;
    
        public class WineFactoryImpl implements WineFactory{
        
        	@Override
        	public void sell() {
        		System.out.println("卖酒");
        	}
        	
        }

        然后定义一个代理类,对酒厂进行代理:

        WineFactoryProxy.java

        package ml.orlion.proxy;
        /**
         * 代理类
         * 对WineFactoryImpl进行代理
         */
        public class WineFactoryProxy implements WineFactory{
        	
        	private WineFactory winef;
        
        	public WineFactoryProxy(WineFactory winef){
        		this.winef = winef;
        	}
        
        	@Override
        	public void sell() {
        		System.out.println("卖酒之前...");
        		winef.sell();
        		System.out.println("卖酒之后...");
        	}
        }

    三、动态代理

        由静态代理的代码可以看到静态代理只能对一个接口进行服务,如果项目中有很多个接口,那么肯定会产生过多的代理。这时候就需要用到动态代理,由一个代理类完成所有的代理功能。动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。

        JDK动态代理中包含一个InvocationHandler接口和一个Proxy类

        (1)InvocationHandler接口

        public interface InvocationHandler {     
            public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
        }

        其中Object porxy:是被代理的对象

        Method method:要调用的方法

        Object[] args:要调用的方法的参数

        (2)Proxy类

        Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:

        public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,     InvocationHandler h)  throws IllegalArgumentException

        其中ClassLoader loader:是类加载器;

        (在java中主要有三种类加载器:

            Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的;

                Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jrelibext目录中的类; 

                AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。          

        )

        Class<?>[] interfaces:得到全部接口;

        InvocationHandler h:得到InvocationHandler接口的子类实例;

        code:

         WineFactory.java和WineFactoryImpl.java和静态代理的代码相同。

        WineFactoryInvocationHandler.java:

        package ml.orlion.proxy;
        
        import java.lang.reflect.InvocationHandler;
        import java.lang.reflect.Method;
        
        /**
         * JDK动态代理类
         * 对WineFactoryImpl进行代理
         */
        public class WineFactoryInvocationHandler implements InvocationHandler{
        
        	private Object target;
        
        	@Override
        	public Object invoke(Object porxy, Method m, Object[] args) throws Throwable {
        		
        		Object result = null;
        		
        		beforeMethod();
        		// 执行
        		result = m.invoke(target, args);
        		
        		afterMethod();
        		return result;
        	}
        	
        	public void beforeMethod(){
        		System.out.println("卖酒之前...");
        	}
        	
        	public void afterMethod(){
        		System.out.println("卖酒之后...");
        	}
        	
        	public Object getTarget() {
        		return target;
        	}
        
        	public void setTarget(Object target) {
        		this.target = target;
        	}
        }

        测试:

        // 产生一个被代理对象
        WineFactory wf = new WineFactoryImpl();
        // 将被代理对象交给InvocationHandler
        WineFactoryInvocationHandler wfih = new WineFactoryInvocationHandler();
        wfih.setTarget(wf);
        // 根据被代理对象产生一个代理
        WineFactory wfp = (WineFactory)Proxy.newProxyInstance(wf.getClass().getClassLoader(), wf.getClass().getInterfaces(), wfih);
        wfp.sell();

        

        除了JDK动态代理外还有一种cglib动态代理,具体可参考文章(本文参考):http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

  • 相关阅读:
    linux下telnet安装与使用
    用日志记录Linux用户执行的每一条命令(history)
    监视网络接口TCP状态信息数据有多种工具或命令。下面举例一些:
    [C#]Winform后台提交数据且获取远程接口返回的XML数据,转换成DataSet
    C#生成Code128码
    BULK INSERT如何将大量数据高效地导入SQL Server
    SQLite中的时间日期函数
    C# winform小票打印
    c#读写txt文件
    C#-WinForm 串口通信
  • 原文地址:https://www.cnblogs.com/orlion/p/5350752.html
Copyright © 2011-2022 走看看