代理模式与动态代理之JDK实现和CGlib实现
静态代理
静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。 由业务实现类、业务代理类 两部分组成。业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作。我们在需要调用业务时,不是直接通过业务实现类来调用的,而是通过业务代理类的同名方法来调用被代理类处理过的业务方法。
静态代理的实现
1:首先定义一个接口,说明业务逻辑。
public interface Star { void confer(); void signContract(); String sign(); void collectMoney(); }
2:然后,定义业务实现类,实现业务逻辑接口
public class RealStar implements Star{ @Override public void confer() { // TODO Auto-generated method stub System.out.println("RealStar.confer "); } @Override public void signContract() { // TODO Auto-generated method stub System.out.println("RealStar.signContract "); } @Override public String sign() { // TODO Auto-generated method stub System.out.println("RealStar.sign "); return "RealStar.sign"; } @Override public void collectMoney() { System.out.println("RealStar.collectMoney "); } }
3:定义业务代理类:通过组合,在代理类中创建一个业务实现类对象来调用具体的业务方法;通过实现业务逻辑接口,来统一业务方法;在代理类中实现业务逻辑接口中的方法时,进行预处理操作、通过业务实现类对象调用真正的业务方法、进行调用后操作的定义。
public class StarProxy implements Star{ private Star star; public StarProxy() { super(); // TODO Auto-generated constructor stub } public StarProxy(Star star) { super(); this.star = star; } @Override public void confer() { System.out.println("ProxyStar.confer"); } @Override public void signContract() { System.out.println("ProxyStar.signContract"); } @Override public String sign() { return star.sign(); } @Override public void collectMoney() { System.out.println("ProxyStar.collectMoney"); }
4:在使用时,首先创建业务实现类对象,然后把业务实现类对象作构造参数创建一个代理类对象,最后通过代理类对象进行业务方法的调用。
public class Main { public static void main(String[] args) { Star realStar=new RealStar(); StarProxy proxy=new StarProxy(realStar); proxy.confer(); proxy.sign(); proxy.collectMoney(); } }
动态代理的第一种实现——JDK动态代理
JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。我们需要做的,只需指定代理类的预处理、调用后操作即可。
public class StarHandle implements InvocationHandler{ private Star realStar; public StarHandle() { super(); } public StarHandle(Star realStar) { super(); this.realStar = realStar; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object object=null; System.out.println("ProxyStar.confer"); System.out.println("ProxyStar.signContract"); if(method.getName().equals("sign")){ object=method.invoke(realStar, args); } System.out.println("ProxyStar.collectMoney"); return object; } }
public class Main { public static void main(String[] args) { Star realStar=new RealStar(); StarProxy proxy=new StarProxy(realStar); proxy.confer(); proxy.sign(); proxy.collectMoney(); } }
动态代理的第二种实现——CGlib
cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理
public class Demo { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(RealStar.class); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invokeSuper(obj, args); } }); Star proxy = (Star) enhancer.create(); System.out.println(proxy.sign()); } }
比较
静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;
JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;
CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;