zoukankan      html  css  js  c++  java
  • 设计模式学习之--代理模式

                       代理模式,顾名思义。意思和我们日常生活中的代理几乎相同。举一个最简单的样例,我们知道。我们的火车站购票有非常多的火车票代售点,这个火车票代售点能够取代我们的火车站的售票处让我们买票。当然,代售点相比于火车站售票点又能够提供电话订票和提前预定,这样,火车票代售点就基本能够实现火车站售票点的基本功能。同一时候还能够提供相对于火车站售票点其它的功能。那么,我们的设计模式中的代理模式就是这个意思。

               在我们的程序中,很多类的方法中我们总须要一些额外的共同的功能。比方日志和性能优化操作。假设在全部 这些类中都增加这些同样的功能,会使我们的程序变得非常冗余。这时,我们的代理模式就起作用了。代理模式在我们的程序中不会影响其原方法的运行。我们用一个代理运行类原有的功能。同一时候增加我们的共同的功能模块,不同类都使用这个总的实体产生代理,这样我们的程序就变得非常健壮了(这也是spring中的AOP思想的实现原理)。

              在我们的初始学习中,我们先了解两种主要的代理模式,静态代理和动态代理:

              静态代理是继承目标类产生一个代理类。然后在目标类的方法中增加我们的其他功能。

             动态代理是目标类和代理类实现同一个接口,在代理类中加入一个目标类的引用加入新的功能。

             当然这些基础的代理仅仅能对特定的类实现不同功能的代理,这样的自然是不合理的,为此,我们的动态代理在我们的jdk中就提供了一个能够为全部对象生成代理的接口,仅仅要实现了这个接口,就能够加入功能并返回这个目标类的代理。

          还有一种已经实现的通用代理就是我们的cglib提供的动态代理。

           这两种动态代理都是须要一个代理类实现一个接口,然后将目标类传入代理类用代理类生产代理对象,但两者是有差别的。

         jdk动态代理:(jdk动态代理生成目标代理类传入的必须是接口,所以必须目标类必需要实现一个接口)

           这里举个工厂生产的样例:

    package com.yc.biz;
    //目标类的接口
    public interface ProductBiz {
    	public void addProduct();
    	
    	public void delProduct();
    	
    	public void updateProduct();
    	
    	public void findall();
    }
    
    
    
    package com.yc.biz;
    
    //目标类
    public class ProductBizImpl implements ProductBiz {
    
    	@Override
    	public void addProduct() {
    		
    		System.out.println("*******************************");
    		System.out.println("加入产品");
    		System.out.println("*******************************");
    		
    	}
    
    	@Override
    	public void delProduct() {
    
    		System.out.println("*******************************");
    		System.out.println("删除产品");
    		System.out.println("*******************************");
    	}
    
    	@Override
    	public void updateProduct() {
    
    		System.out.println("*******************************");
    		System.out.println("改动产品");
    		System.out.println("*******************************");
    		
    	}
    
    	@Override
    	public void findall() {
    
    		System.out.println("*******************************");
    		System.out.println(" 查询全部的产品");
    		System.out.println("*******************************");
    		
    	}
    
    }
    
    我们要在这个类上加上权限的检查(代理模式这时候假设全部业务类都须要这功能时。全部用这个代理类生产目标类就能够加上权限检查了,节省了非常多代码)

    我们的代理类:

    package com.yc.advice;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    
    //这个类是一个切面类, 完毕的功能是向目标类的目标方法增加功能( 增强)
    public class RightAdvice implements InvocationHandler {
    	//代理模式中一定要有目标类的引用
    	private Object targetObject;  //注意。这个就是目标类的引用
    	
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		String methodName=method.getName();
    		if(  methodName.startsWith("add")  ||  methodName.startsWith("del")|| methodName.startsWith("update") || methodName.startsWith("modify")  ){
    			//在invoke中增加您要增强的代码
    			check();   //前置增强。在激活调用相应方法前增加的代码
    		}
    		//调用目标的相应的方法。这里通过反射激活目标类的方法 
    		Object returnValue=method.invoke(targetObject, args);   // object is not an instance of declaring class
    		return returnValue;
    	}
    	
    	//创建一个方法来完毕创建代理对象
    	public Object createInstance( Object  targetObject  ){
    		this.targetObject=targetObject;
    		//生成一个代理对象..
    		//  生成一个代理对象。这个代理对象是依据  目标对象的接口生成的。

    Object obj= Proxy.newProxyInstance( targetObject.getClass().getClassLoader() , targetObject.getClass().getInterfaces() , this ); //在client,我们调用 createInstance()得到一个代理对象,再调用这个代理对象的 方法. -> 它就会自己主动加调( 由于this ) -> invoke return obj; } //增强 private void check(){ System.out.println("***********************************"); System.out.println("权限检查"); System.out.println("***********************************"); } }

    測试类:

    package com.yc.biz;
    
    import com.yc.advice.LogAdvice;
    import com.yc.advice.RightAdvice;
    
    public class Test1 {
    
    	public static void main(String[] args) {
    		RightAdvice ra=new RightAdvice();
    		
    		ProductBiz pb=new ProductBizImpl();
    		
    		ProductBiz productBizProxy=(ProductBiz) ra.createInstance(pb);
    		productBizProxy.addProduct();
    		productBizProxy.delProduct();
    		productBizProxy.updateProduct();
    		productBizProxy.findall();
    		
    		
    		
    	}
    
    }
    这个就是jdk的动态代理。

    以下是cglib的动态代理。使用cglib代理须要一个jar包,这里提供下载地址:


    cglib的代理类也是须要实现一个接口。我们还是用这个工厂的样例来展示:

    cglib代理(使用它的目标类不须要实现接口,它的原理是通过目标类实现一个子类来实现的)

    使用方法和jdk动态代理是一样的,以下给出代理类:

    package com.yc.advice;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    
    //这个类是一个切面类, 完毕的功能是向目标类的目标方法增加功能( 增强)
    public class RightAdvice implements MethodInterceptor {
    	//代理模式中一定要有目标类的引用
    	private Object targetObject;  //注意,这个就是目标类的引用
    	
    	@Override
    	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable {
    		String methodName=method.getName();
    		if(  methodName.startsWith("add")  ||  methodName.startsWith("del")|| methodName.startsWith("update") || methodName.startsWith("modify")  ){
    			//在invoke中增加您要增强的代码
    			check();   //前置增强
    		}
    		//调用目标的相应的方法
    		Object returnValue=method.invoke(targetObject, args);   // object is not an instance of declaring class
    		return returnValue;
    	}
    	
    	
    	
    	//创建一个方法来完毕创建代理对象
    	public Object createInstance( Object  targetObject  ){
    		this.targetObject=targetObject;   //  => Object
    		Enhancer enhancer=new Enhancer();
    		
    		enhancer.setSuperclass(   targetObject.getClass() );
    		//enhancer.setClassLoader(   targetObject.getClass().getClassLoader()  );
    		enhancer.setCallback(    this  );
    		
    		return enhancer.create();  //创建代理类对象.
    	}
    	
    	//增强
    	private void check(){
    		System.out.println("***********************************");
    		System.out.println("权限检查");
    		System.out.println("***********************************");
    	}
    
    }
    

    使用方法是一样的 。代理模式就是这两个牛逼点了了。





           

                           


        

            


  • 相关阅读:
    理财技术+人生感悟(转)
    程序员每天每月每年需要做的事(转)
    数据库常用函数(数字函数)
    数据库之常用函数 (日期函数)
    Qt初级-头文件
    Qt初级-成员函数(二)
    Qt初级-成员函数(一)
    Qt初级-Qt格式(二)
    Qt初级-Qt格式(一)
    Qt初级-Qt继承表
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6805882.html
Copyright © 2011-2022 走看看