46、设计模式之动态代理模式

代理模式分为两种,静态代理 和 动态代理,静态代理简单易懂,对于新手来说便于理解,但实际运用到项目中代码量以及维护量都是非常大的,在企业级项目中不推荐使用这种方式,用于学习或者做毕设还是可以的,本文中只阐述动态代理模式,记录在这用于加深自身理解,同时希望能对您有所帮助。

JDK 动态代理

这种方式,只能对实现了接口的类生成代理,JDK动态代理采用委托机制,动态实现接口类,在动态生成的实现类中委托hanlder去调用原始实现类方法,但对于没有实现接口的类来说,就不适用了

/**
 * 接口
 */
public interface Person {
    void say();
}
/**
 * 实现类
 * 对于JDK 动态代理来说,只有 实现了接口的类才可以使用这种代理方式
 */
public class Children implements Person {
    @Override
    public void say() {
        System.out.println("你好,世界。");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDK 动态代理
 */
public class JDKProxy implements InvocationHandler {

    private Object targetObject;

    public Object newProxy(Object targetObject){
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
            targetObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("练习发音");
        // 这里切勿 使用 proxy 传参变量,会报错哟
        // 在newProxy 方法 接收的参数targetObject,目的是在这里被运用
        Object result = method.invoke(targetObject, args);
        System.out.println("恭喜成功");
        return result;
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {

    public static void main(String[] args) {

        Person person = (Person) new JDKProxy().newProxy(new Children());
        person.say();

        // 报错信息:Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to Children
        // 	at Main.main(Main.java:12)
        // JDK 动态代理,动态生成的实现类 和 Children 并无关系,所以这里强转会报错
        // 这种方式,采用委托机制,在动态生成的实现类里,委托Handler去调用原始实现类中的方法
        /*
        Children children = (Children) new JDKProxy().newProxy(new Children());
        children.say();
        */


    }
}

CGlib 动态代理

这种方式,不限制类是否实现了接口,相对于JDK 动态代理改进不少,同时又比JDK动态代理具备更高效的执行效率。

/**
 * 没有实现接口的类,用于Cglib 动态代理
 */
public class User {

    public void shopping(){
        System.out.println("去海吉星采购");
    }
}

 

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {

    private Object targetObject;

    public Object newProxy(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(this);
        Object object = enhancer.create();
        return object;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("开始处理……");
        Object result = method.invoke(targetObject, args);
        System.out.println("结束活动");
        return result;
    }
}

public class Main {

    public static void main(String[] args) {
        User user = (User) new CglibProxy().newProxy(new User());
        user.shopping();
    }
}

Cglib方式,上面的代码如要运行成功,还需 额外引入 cglib-2.2.jar 和 asm-3.1jar,这两个包,特别注意的事,cglib-3.1.jar,引入会报错,由于时间关系,没有特别深入的了解原因,换成 2.2版本即可

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值