代理模式

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

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方式要更为合适一些。
原文地址:https://www.cnblogs.com/Ch1nYK/p/8862037.html