动态代理的作用
我们要清楚动态代理的主要作用:
动态的创建代理对象,降低程序之间的耦合,提高代码的复用。
我们不直接和我们真实访问的对象进行打交道,而是和其代理对象打交道。
例如我们向代理买东西而不是直接从厂家买东西。
经销商会被厂家的产品进行加工或包装后再出售,并且会有额外的方式。
动态代理的方式
有两种:基于接口的代理方式&基于子类的代理方式。
其特点
动态代理的字节码随用随创建,随用随加载。和装饰者模式不同,装饰者模式需要提前写好一个代理类。他的作用就是在不修改源码的基础上对方法增强
基于接口的动态代理
涉及到的类Proxy,提供者为jdk官方。
首先要通过Proxy.newProxyInstance创建代理对象,要求被代理的对象至少实现一个接口。Proxy.newProxyInstance的三个参数:
ClassLoader loader,用于加载被代理对象的字节码的,通过为固定的
Class<?>[] interfaces:用于让代理对象和被代理对象有相同的方法,通过也是固定的
InvocationHandler h:提供增强的代码,是我们重点要书写的内容。
public class Consumer { public static void main(String[] args) { final Producer producer = new Producer(); IProducer iProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {// 这种写法是一个匿名的内部类 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy是代理对象的引用,method是被代理对象只要执行来接口中的方法就会先经过这个,args是方法的传参 //Object返回是一样的 Object value = null; if(method.getName().equals("sale")){ method.invoke(producer,(Float)args[0]*0.8f);//invoke的时候一定要写一个对象 } return value; } }); iProducer.sale(1000); } }
public interface IProducer { void sale(float money); void afterService(); }
public class Producer implements IProducer{ public void sale(float money){ System.out.println("厂商卖出:"+money); } public void afterService(){ System.out.println("厂商的售后服务"); } }
这就是一个很简单的动态代理的实现,但其实我还是不太理解这个动态代理的魔力,因为在这里例子中,其实被代理的对象是完全暴露在程序中的,那么我们为什么要辛苦的创建一个代理类尼》这完全没有体现出动态代理的优势。
基于子类的动态代理
public class Consumer { public static void main(String[] args) { final Producer producer = new Producer(); Producer producer1 = (Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //0是代理对象,method是被代理对象中执行的方法,objects为方法的参数,methodProxy为被代理对象 Object value = null; if(method.getName().equals("sale")){ value = method.invoke(producer, (Float)objects[0]*0.8f); } return value; } }); producer1.sale(1000); } } public class Producer { public void sale(float money){ System.out.println("厂商卖出:"+money); } public void afterService(){ System.out.println("厂商的售后服务"); } }
要求:被代理的对象不能是final类,可以被继承。在pom中添加cglib的引用,然后使用Enhancer类中的create方法创建代理子类,其中需要的参数如上,需要实现一个Callback进行方法增强。
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>LATEST</version> </dependency>
至此,动态代理的只是回归完毕,接下来就是如何用动态代理解决事务管理中的胶水代码问题。