zoukankan      html  css  js  c++  java
  • 代理技术



    什么代理?

    一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

    优点

    如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。

    AOP
    系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示:
                                  安全       事务         日志
    StudentService  ------|----------|------------|-------------
    CourseService   ------|----------|------------|-------------
    MiscService       ------|----------|------------|-------------
    用具体的程序代码描述交叉业务:
    method1         method2          method3
    {                      {                       {
    ------------------------------------------------------切面
    ....            ....              ......
    ------------------------------------------------------切面
    }                       }                       }
    交叉业务的编程问题即为面向方面的编程(Aspect oriented program ,简称AOP),AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
    ------------------------------------------------------切面
    func1         func2            func3
    {             {                {
    ....            ....              ......
    }             }                }
    ------------------------------------------------------切面
    使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。

    动态代理的工作原理:

    1)Client(客户端)调用代理,代理的构造方法接受一个InvocationHandler,client调用代理的各个方法,代理的各个方法请求转发给刚才通过构造方法传入的handler对象,又把各请求分发给目标的相应的方法。就是将handler封装起来,其中this引用了当前的放(发来什么请求就接受哪个方法)。
    猜想分析动态生成的类的内部代码:
    1、动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和一个如下接受InvocationHandler参数的构造方法。
    2、构造方法接受一个InvocationHandler对象,接受对象了要干什么用呢?该方法内部的代码会是怎样的呢?
    实现Collection接口的动态类中的各个方法的代码又是怎样的呢?InvocationHandler接口中定义的invoke方法接受的三个参数又是什么意思?图解说明如下:

    分析为什么动态类的实例对象的getClass()方法返回了正确结果呢?
    为何动态类的实例对象的getClass()方法返回了正确结果,而没调用invoke方法:
    因为代理类从Object上继承了许多方法,其中只对三个方法(hashCode、equals和toString)进行开发,委托给handler去自行处理,对于它身上其他方法不会交给代理类去实现,所以对于getClass()方法,还是由Object本身实现的。即proxy3.getClass(),该是什么结果还是什么结果,并不会交给invoke方法处理。

    例子

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.ArrayList;
    import java.util.Collection;
    
    public class ProxyTest {
    	public static void main(String[] args)throws Exception{
    		Class ClazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);      //获得代理类的字节码
    		System.out.println(ClazzProxy);
    		Constructor[] cons=ClazzProxy.getConstructors();                                             //获得代理类的构造方法
    		StringBuilder sb=new StringBuilder(); 
    		for(Constructor con:cons){
    			System.out.print(con.getName());
    			sb.append('(');
    			Class[] cls=con.getParameterTypes();
    			for(Class cl:cls){
    				sb.append(cl.getName()+',');
    			}
    			if(cls!=null&&cls.length!=0)
    			sb.deleteCharAt(sb.length()-1);
    			sb.append(')');
    		}
    		System.out.println(sb.toString());
    		
    		
    		System.out.println("Method----------------------------------------");
    
    		Method[] meths=ClazzProxy.getMethods();                                                 //获得代理类的成员方法
    
    		for(Method meth:meths){
    			StringBuilder sb1=new StringBuilder(); 
    			System.out.print(meth.getName());
    			sb1.append('(');
    			Class[] cls=meth.getParameterTypes();
    			for(Class cl:cls){
    				sb1.append(cl.getName()+',');
    			}
    			if(cls!=null&&cls.length!=0)
    			sb1.deleteCharAt(sb1.length()-1);
    			sb1.append(')');
    			System.out.println(sb1.toString());
    		}
    		
    		System.out.println("----------------------------------------------");
    		
    		Constructor con=ClazzProxy.getConstructor(InvocationHandler.class);     //获得构造方法
    		class Ivct implements InvocationHandler{
    			public void invoke(){}
    
    			@Override
    			public Object invoke(Object arg0, Method arg1, Object[] arg2)
    					throws Throwable {
    				// TODO Auto-generated method stub
    				return null;
    			}
    		}
    		Collection coll=(Collection)con.newInstance(new Ivct());
    		
    		//coll.size();                                                    //size会调用InvocationHandler的invoke方法,但是上面的invoke方法返回值是null,而
    																			//size需要的是一个int类型的返回值,所以会报错
    		
    		
    		
    		
    		Collection proxy2=(Collection)Proxy.newProxyInstance(
    				Collection.class.getClassLoader(),
    				new Class[]{Collection.class},
    				new InvocationHandler(){
    
    					 ArrayList al=new ArrayList();
    					public Object invoke(Object proxy, Method method,
    							Object[] args) throws Throwable {
    						Object obj=method.invoke(al, args);
    						System.out.println(obj+"Test..........");
    						return obj;
    					}
    					
    					
    				});
    		proxy2.add("zs");                                      //每次调用add方法时,add就会调用InvocationHandler的invoke方法
    		proxy2.add("ls");
    		proxy2.add("ww");
    		System.out.println(proxy2);
    		System.out.println(proxy2.size());
    	}
    }
    



  • 相关阅读:
    JDBC连接MySQL并且查询操作。
    struts
    KMP 剪花布条hdoj2087
    线段树---敌兵布阵hdoj 1166
    设计模式----观察者模式
    线段树--hdoj1754
    ZOJ 2283 Challenge of Wisdom
    SGU 134 Centroid
    UVA 1637 Double Patience
    HDU 4389 X mod f(x)
  • 原文地址:https://www.cnblogs.com/lisisong/p/5122616.html
Copyright © 2011-2022 走看看