动态代理的两种实现方式小案例

关于反射和动态代理的使用

动态代理的方式简化业务层的大量重复代码

package com.xwl;
/**
 * 动态代理
 * @author Administrator
 *
 *我们可以使用动态代理的方式简化销售公司的大量重复代码
 *
 */
//苹果需要生产四种产品 交给中国工厂
interface Iphone{   
    public void product6s();
    public void product6Plus();
    public void product7();
    public void productX();
}
//生产厂商生产苹果手机
class Phone implements Iphone{
    public void product6s() {
        System.out.println("6s");
    }
    public void product6Plus() {
        System.out.println("6Plus");
    }
    public void product7() {
        System.out.println("7");
    }
    public void productX() {
        System.out.println("X");
    }
}

//销售公司Agent 宣传  销售
class Agent{
    //首先我需要手机
    private Iphone phone;

    public Iphone getPhone() {
        return phone;
    }
    public void setPhone(Iphone phone) {
        this.phone = phone;
    }
    //  **1.宣传 我们 2.生产(phone.product6s()) 3.销售发货**
    public void product6s(){
        System.out.println("宣传");
        phone.product6s();//生产的什么?
        System.out.println("销售和发货");
    }
    // **1.宣传 我们 2.生产(phone.product6Plus()) 3.销售发货**
    public void product6Plus(){
        System.out.println("宣传");
        phone.product6Plus();
        System.out.println("销售和发货");
    }
    // **1.宣传 我们 2.生产(phone.product7()) 3.销售发货**
    public void product7(){
        System.out.println("宣传");
        phone.product7();
        System.out.println("销售和发货");
    }
    // **1.宣传 我们 2.生产(phone.productX()) 3.销售发货**
    public void productX(){
        System.out.println("宣传");
        phone.productX();
        System.out.println("销售和发货");
    }
}
public class Test_fanse {
    public static void main(String[] args) {

    }
}

我们可以通过动态代理的方式简化销售公司的任务,动态代理的实现有两种一种是JDK的原生方式,另一种是封装了(字节码处理框架ASM)的CGLIB动态代理实现。

首先我们要细化上面的代码

苹果生产厂商提供的生产苹果手机的接口(规范)

package com.xwl;
public interface PhoneService {
    //苹果生产四种产品 交给中国工厂
        public void product6s();
        public void product6Plus();
        public void product7();
        public void productX();
}

中国富士康给出了实现制造出来实现(实现)

package com.xwl;
public class PhoneServiceImpl implements PhoneService {

        public void product6s() {
            System.out.println("6s");
        }
        public void product6Plus() {
            System.out.println("6Plus");
        }
        public void product7() {
            System.out.println("7");
        }
        public void productX() {
            System.out.println("X");
        }
}

一、JDK实现动态代理(销售公司)

代理对象JdkProxy :

    package com.xwl;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    public class JdkProxy implements InvocationHandler{
        //要代理的对象
        private Object target;
        public JdkProxy(Object target) {
            super();
            this.target = target;
        }
        public JdkProxy() {
            super();
        }
        //给一个代理对象
        public Object getProxy(){
             return Proxy.newProxyInstance(Thread.currentThread()
                        .getContextClassLoader(), target.getClass().getInterfaces(),
                        this);
        }
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("宣传");
            Object reslut = method.invoke(target, args);
            System.out.println("销售和发货");
            return reslut;
        }
    }

生产出了一个phone7开始宣传:

package com.xwl;
public class TestJdk {
    public static void main(String[] args) {
        PhoneService phoneService = new PhoneServiceImpl();
        JdkProxy jdkProxy = new JdkProxy(phoneService);
        PhoneService proxy = (PhoneService) jdkProxy.getProxy();
        proxy.product7();
    }
}

CGLIB实现动态代理

代理对象CglibProxy :

package com.xwl;    
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

    public Object intercept(Object proxy, Method method, Object[] args,
            MethodProxy methodProxy) throws Throwable {
        System.out.println("宣传");
        Object result = methodProxy.invokeSuper(proxy, args);
        System.out.println("销售和发货");
        return result;
    }
}

生产出来了一个6s开始宣传:

package com.xwl;
import org.springframework.cglib.proxy.Enhancer;
public class TestCglib {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(PhoneServiceImpl.class);//继承被代理类
        enhancer.setCallback(new CglibProxy());//设置回调
        PhoneServiceImpl PhoneProxy = (PhoneServiceImpl) enhancer.create();//生成代理对象
        PhoneProxy.product6s();
    }
}

总结

动态代理的好处是什么?
Java动态代理的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法就可以)。
动态代理和静态代理的区别?
1.静态代理类:由程序员创建或者由第三方工具生成,再进行编译;在程序运行之前,代理类的.class文件已经存在了。
动态代理类:在程序运行时,通过反射机制动态生成。
2.静态代理类通常只代理一个类。动态代理类通常代理接口下的所有类。
3.静态代理事先知道要代理的是什么。动态代理事先不知道要代理的是什么,只有在运行的时候才能确定。
4.动态代理的调用处理程序必须事先InvocationHandler接口,及使用Proxy类中的newProxyInstance方法动态的创建代理类。
5.Java动态代理只能代理接口,要代理类需要使用第三方的CLIGB等类库。
JDK动态代理和CGLIB动态代理的区别?
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
Enhancer
Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作。

猜你喜欢

转载自blog.csdn.net/xwl_java/article/details/82080243