设计模式-代理模式-java动态代理

在框架开发中动态代理模式使用较为普遍,与此同时JDK为我们提供了好用的接口,
1.InvocationHandler(代理接口,代理类需要实现它)
2.Proxy(代理类,用来实现代理操作)

实例

项目结构

在这里插入图片描述

Proxy(自定义的代理接口类,并非jdk自带的)
public interface Proxy {
    void show(User user);
}
POJO 类 User
@AllArgsConstructor
@ToString
public class User {
    private String name;
    private Integer age;
}
ProxyUser(代理类)
@AllArgsConstructor
public class ProxyUser implements InvocationHandler {
    private Proxy proxy;

    public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println("ProxyUser :: invoke() ----------进入-----------");
        method.invoke(proxy,args);
        System.out.println("ProxyUser :: invoke() ----------退出-----------");
        return null;
    }
}
TargetUser (实际目标类)
public class TargetUser implements Proxy {

    public void show(User user){
        System.out.println("TargetUser :: show(): "+user.toString());
    }

}
测试类 Test
public class Test {
    public static void main(String[] args) {
        TargetUser targetUser=new TargetUser();
        InvocationHandler invocationHandler=new ProxyUser(targetUser);
        com.ecit.lyy.proxy.dynamic_proxy.Proxy proxy=(com.ecit.lyy.proxy.dynamic_proxy.Proxy)Proxy.newProxyInstance(
                invocationHandler.getClass().getClassLoader(),
                targetUser.getClass().getInterfaces(),
                invocationHandler);
        proxy.show(new User("show.tom",15));


    }
}
结果如下
ProxyUser :: invoke() ----------进入-----------
TargetUser :: show(): User(name=show.tom, age=15)
ProxyUser :: invoke() ----------退出-----------

注意点

1.代理类实现的是jdk中的InvocationHandler接口,而非我们自定义的接口。
2.目标类实现的是自定义的Proxy接口,而非JDK自带的Proxy。
3.代理类通过实现InvocationHandler的invoke方法,来处理实际业务逻辑,我们可以在method.invoke()前后加入我们自己的逻辑。
4.使用Proxy.newProxyInstance来实现代理,它有三个参数

源码(它们的使用方式在源码里都有)

InvocationHandler (接口)
package java.lang.reflect;


public interface InvocationHandler {

   
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

Proxy(jdk)
package java.lang.reflect;
import (省略。。)

/**
 *     InvocationHandler handler = new MyInvocationHandler(...);
 *     Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
 *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
 *                     newInstance(handler);
 * 或者:
 *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
 *                                          new Class[] { Foo.class },
 *                                          handler);
 */
public class Proxy implements java.io.Serializable {

    private static final long serialVersionUID = -2222568056686623797L;

    private static final Class<?>[] constructorParams =
        { InvocationHandler.class };
	......
    protected InvocationHandler h;
    private Proxy() {
    }
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }
    

	......
    @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);
        }

    
        Class<?> cl = getProxyClass0(loader, intfs);//获取代理类

        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

   ......
   
    public static boolean isProxyClass(Class<?> cl) {
        return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
    }

 
    @CallerSensitive
    public static InvocationHandler getInvocationHandler(Object proxy)
        throws IllegalArgumentException
    {
        /*
         * Verify that the object is actually a proxy instance.
         */
        if (!isProxyClass(proxy.getClass())) {
            throw new IllegalArgumentException("not a proxy instance");
        }

        final Proxy p = (Proxy) proxy;
        final InvocationHandler ih = p.h;
        if (System.getSecurityManager() != null) {
            Class<?> ihClass = ih.getClass();
            Class<?> caller = Reflection.getCallerClass();
            if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
                                                    ihClass.getClassLoader()))
            {
                ReflectUtil.checkPackageAccess(ihClass);
            }
        }

        return ih;
    }

    private static native Class<?> defineClass0(ClassLoader loader, String name,
                                                byte[] b, int off, int len);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盒曰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值