文章目录

  • 1、简介
  • 2、静态代理
  • 3、动态代理
  • 3.1 JDK动态代理实现
  • 3.2 CGLIB动态代理实现
  • 4、动态代理原理



1、简介

代理模式23种Java常用设计模式之一。代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问。

代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。

java名词解释 java名词解释proxy_动态代理

2、静态代理

(1)接口类

public interface IUserService {
    void add();
}

(2)实现类

public class UserService implements IUserService {
    public void add() {
        System.out.println("add");
    }
}

(3)代理类

public class UserServiceProxy implements IUserService {
    private IUserService userService;
    public UserServiceProxy(IUserService userService) {
        this.userService = userService;
    }
    @Override
    public void add() {
        System.out.println("do something before");
        this.userService.add();
        System.out.println("do something after");
    }
}

(4)启动类

public static void main(String[] args) {
        IUserService userService = new UserService();
        UserServiceProxy proxy = new UserServiceProxy(userService);
        proxy.add();
    }

3、动态代理

静态代理中一个代理只能代理一种类型,而且是在编译器编译前就已经确定被代理的对象。而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象。

原理:在运行时期,构建需要被代理类的代理对象,这个代理对象可以针对不同的被代理类组装成不同的内容,因此可以对各种对象进行代理,这种方式是通过Java的反射机制实现的。

实现动态代理的两种方案:

  • JDK动态代理:内置在JDK中,不需要引入第三方jar,使用简单,但功能比较弱。
  • CGLIB动态代理:使用第三方CGLIB库,总体性能比JDK动态代理好,且功能强大。
3.1 JDK动态代理实现

(1)接口类

public interface IUserService {
    void add();
}

(2)实现类

public class UserService implements IUserService {
    public void add() {
        System.out.println("add");
    }
}

(3)代理类

public class SDKDynamicProxy implements InvocationHandler {
    private Object object;
    public SDKDynamicProxy(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("do something before");
        Object invoke = method.invoke(object, args);
        System.out.println("do something after");
        return invoke;
    }
}

(4)启动类

public static <T> T getProxy(Class<T> clazz, T obj) {
        SDKDynamicProxy proxy = new SDKDynamicProxy(obj);
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, proxy);
    }
    public static void main(String[] args) {
        IUserService userService = getProxy(IUserService.class, new UserService());
        userService.add();
    }
3.2 CGLIB动态代理实现

(1)添加依赖

<dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

(2)接口类

public interface IUserService {
    void add();
}

(3)实现类

public class UserService implements IUserService {
    public void add() {
        System.out.println("add");
    }
}

(4)代理类

public class CglibDynamicProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("do something before " + method.getName());
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("do something after " + method.getName());
        return invoke;
    }
}

(5)启动类

public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);
        enhancer.setCallback(new CglibDynamicProxy());
        UserService userService = (UserService) enhancer.create();
        userService.add();
    }

4、动态代理原理

从上面的例子可以看到动态代理对象是在运行过程中创建的:

Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, proxy);

Proxy.newProxyInstance方法中会先创建代理类:

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                throw new IllegalArgumentException(e.toString());
            }

再用反射机制创建代理类的对象:

final Constructor<?> cons = cl.getConstructor(constructorParams);	// cl为代理类
            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});

我们可以看看代理类具体的实现,先获取代理类的字节码:

private static void generateProxyClass() {
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", UserService.class.getInterfaces());
        String path = "/path/to/Proxy.class";
        try (FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(classFile);
            fos.flush();
        } catch (Exception e) {
            System.out.println("写文件错误");
        }
    }

得到字节码后反编译出实现代码:

public final class $Proxy0 extends Proxy implements IUserService {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void add() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.example.aop.service.IUserService").getMethod("add");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

我们可以看到代理类实现了被代理类的接口,所以外部可以直接将代理类对象转化为接口对象来使用,调用代理对象的方法时,执行的是构造参数InvocationHandler的invoke方法:

public final void add() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

以上是JDK动态代理的实现原理,Cglib动态代理的情况类似。