zoukankan      html  css  js  c++  java
  • 代理模式

    代理模式是一种很常见的设计模式,代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

    3种实现方式

    1. 静态代理
    2. 动态代理
      1. jdk代理
      2. cglib代理

    静态代理

    public interface Server {
    	void send();
    } 
    
    public class ServerTarget implements Server {
    	@Override
    	public void send() {
    		System.out.println("send!");
    	}
    }
    
    public class StaticProxy implements Server {
    	private Server server;
    	public StaticProxy(Server server){
    		this.server = server;
    	}
    	@Override
    	public void send() {
    		System.out.println("before!");
    		server.send();
    		System.out.println("afer!");
    	}
    }
    
        public class TestMain {
        public static void main(String[] args) {
        	Server s = new StaticProxy(new ServerProxy());
        	s.send();
        }		
    }
    

    优点:在不修改目标类的情况下,可以对目标类进行扩展。
    缺点:代理类和目标类需要实现一样的接口,假如代理类很多,维护起来就很麻烦。

    动态代理---jdk代理


    基于静态代理类代码的基础上,再多写一些类,后面基于静态代理类再说下区别。
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class DynamicProxy implements InvocationHandler {
    	private Object obj;
    	public DynamicProxy(Object obj){
    		this.obj = obj;
    	}
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		System.out.println("before");
    		Object result = method.invoke(this.obj, args);
    		System.out.println("after");
    		return result;
    	}
    
    }
    
    public interface Client {
    	void receive();
    }
    
    public class ClientTarget implements Client {
    	@Override
    	public void receive() {
    		System.out.println("receive!");
    	}
    }
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    public class TestMain {	
        public static void main(String[] args) {
        	Server ser = new ServerTarget();
        	InvocationHandler handler =  new DynamicProxy(ser); 
        	Server s = (Server)Proxy.newProxyInstance(handler.getClass().getClassLoader(),
        											ser.getClass().getInterfaces(),
        											handler);
        	s.send();
        	Client cli = new ClientTarget();
        	InvocationHandler handlers =  new DynamicProxy(cli); 
        	Client c = (Client)Proxy.newProxyInstance(handlers.getClass().getClassLoader(),
        											cli.getClass().getInterfaces(),
        											handlers);
        	c.receive();
        }	
    }
    
    假如上面的代码是基于静态代理类的模式来实现,其维护成本就很高了,代理类ServerProxy对目标类ServerTarget的方法进行了扩展,且代理类StaticProxy和目标类ServerTarget都实现了Server接口,现在新的目标类ClientTarget也有相同的需求,那就必须也实现Server接口了,动态代理就是将相同的业务需求抽象出来,不需要实现代理类的接口,只需要实现InvocationHandler接口,维护性相对于静态代理来说,已经好很多了。
    

    动态代理---cglib代理
    静态代理和jdk动态代理,目标对象都需要实现接口,有没有不需要实现接口的方法呢,答案就是cglib代理。cglib代理是以目标对象子类的方式类实现代理的。需要下载cglib的jar包,这里导入的cglib-nodep-2.1_3.jar。

    	public class ServersTarget {
    	
    	public void send() {
    		System.out.println("send!");
    	}
    }
    ```java
    import java.lang.reflect.Method;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibProxy implements MethodInterceptor{
    
    	private Object target;
        public CglibProxy(Object target) {
            this.target = target;
        }
        public Object getProxyInstance(){
            //1.工具类
            Enhancer en = new Enhancer();
            //2.设置父类
            en.setSuperclass(target.getClass());
            //3.设置回调函数
            en.setCallback(this);
            //4.创建子类(代理对象)
            return en.create();
    
        }
    	@Override
    	public Object intercept(Object obj, Method method, Object[] args,
    			MethodProxy proxy) throws Throwable {
    		System.out.println("before");
    		Object returnValue = method.invoke(target, args);
    		System.out.println("after");
    		return returnValue;
    	}
    }
    
    	public class TestMain {
        public static void main(String[] args) {
        	ServersTarget st = new ServersTarget();
        	ServersTarget stProxy  = (ServersTarget)new CglibProxy(st).getProxyInstance();
        	stProxy.send();
        }	
    }
    
    由于CGLib是采用动态创建子类的方法,对于final标识的类无法被继承,会抛出异常。
    对于final标识的方法,intercept不生效,直接调用父类方法,不能代理。
    CGLib动态代理对象性能比JDK动态代理对象的性能高不少,但CGLib在创建代理对象时所花费的时间却比JDK多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。
  • 相关阅读:
    hdoj 3599 最小费用最大流
    poj 2516 最小费用最大流
    poj 3281 最大流拆点
    poj 3436 网络最大流加打印路径
    邻接表模板
    hdu 2102 搜索
    hdoj 1533 最小费用最大流
    HDU 1231 最大连续子序列
    NYOJ 2 括号配对问题
    POJ 1163 / NYOJ 16 The Triangle(数字三角形)
  • 原文地址:https://www.cnblogs.com/Ch1nYK/p/8862037.html
Copyright © 2011-2022 走看看