动态代理的作用

我们要清楚动态代理的主要作用:
动态的创建代理对象,降低程序之间的耦合,提高代码的复用。
我们不直接和我们真实访问的对象进行打交道,而是和其代理对象打交道。
例如我们向代理买东西而不是直接从厂家买东西。
经销商会被厂家的产品进行加工或包装后再出售,并且会有额外的方式。

动态代理的方式

有两种:基于接口的代理方式&基于子类的代理方式。

其特点

动态代理的字节码随用随创建,随用随加载。和装饰者模式不同,装饰者模式需要提前写好一个代理类。他的作用就是在不修改源码的基础上对方法增强

基于接口的动态代理

涉及到的类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>

至此,动态代理的只是回归完毕,接下来就是如何用动态代理解决事务管理中的胶水代码问题。