Java动态代理的原理

动态代理是使用非常广泛的技术,诸如大名鼎鼎的spring、mybatis等框架都大量使用动态代理。动态代理区别于静态代理的地方在于:静态代理需要为每一个被代理类都创建一个代理类,在编译期代理类就已经生成,而动态代理则是在程序运行期动态地生成代理类,所有被代理对象的执行逻辑都被转移到InvocationHandler对象的invoke方法,在invoke方法里通过反射来调用被代理的对象方法,当然也可以执行其它的逻辑。动态代理的一个显而易见的好处是:不用为每个被代理类都手动创建一个代理类。

按照惯例,先谈使用再讲原理。举个例子先。

场景:七夕临近,公司交友社团本着消灭单身狗的美好愿景,为闷骚的程序猿(媛)们开通了月老服务,任何有心仪目标但是又羞于开口的单身程序狗都可以委托“月老”来约心中的男神女神出来。

Suitor(追求者)接口

public interface Suitor {

    void sayHi(Beauty beauty);

}

Programmer(程序猿)

public class Programmer implements Suitor {

    @Override
    public void sayHi(Beauty beauty) {
        System.out.println("Hello, " + beauty.getName() + "! Would you like to have dinner with me tonight?");
    }

}

Beauty(MM)

public class Beauty {

    private String name;

    public Beauty(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}

处理邀请MM动作的InvocationHandler

public class SuitorInvocationHandler implements InvocationHandler {

    Suitor suitor;

    public SuitorInvocationHandler(Suitor suitor) {
        this.suitor = suitor;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(suitor, args);
    }

}

测试,创建代理对象并对MM发出邀请

public class DynamicProxyTest {

    @Test
    public void test() {
        Beauty beauty = new Beauty("MM");
        InvocationHandler handler = new SuitorInvocationHandler(new Programmer());
        Suitor suitor = (Suitor) Proxy.newProxyInstance(Suitor.class.getClassLoader(), new Class<?>[]{Suitor.class}, handler);
        suitor.sayHi(beauty);
    }

}

结果

Hello, MM! Would you like to have dinner with me tonight?

可见,代理对象成功地激发了被代理对象想执行的业务逻辑。

废话不多说,看看代理对象到底是如何生成的,业务逻辑又是如何转嫁到InvocationHandler上的。

Proxy.newProxyInstance中调用生成代理类的逻辑 Class<?> cl = getProxyClass0(loader, intfs);

@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         * 生成代理类
         */
        Class<?> cl = getProxyClass0(loader,
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值