使用场景:
保护目标对象 增强目标对象 降低系统的耦合度 易于扩展
特点:
jdk动态代理被代理对象必须实现一个接口
实现方式:
- 静态代理
- 动态代理:jdk动态代理、cglib动态代理
jdk动态代理
package com.wh.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Object target;
public Object getInstance(Object target) throws Exception{
this.target = target;
Class<?> clazz = target.getClass();
//1.newProxyInstance做了什么操作,传入三个参数的意义
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before ();
//2.method是什么方法、返回的是什么对象
Object invoke = method.invoke(this.target, args);
after();
return invoke;
}
private void before(){
System.out.println("前置方法!");
}
private void after(){
System.out.println("后置方法!");
}
}
总结:首先jdk动态代理实现了invocationhandler接口实现了invoke方法
1.proxy相当于是一个工具类,用来生成一个代理类并存储在缓存中,该继承了proxy实现了被代理对象的接口,只有一个有参传入invocationghandler对象的构造器;
2.invoke方法是在执行内存中生成的代理类的方法里执行的
1.jdk动态代理使用的一个工具类:Proxy.newProxyInstance()
public class Proxy implements java.io.Serializable {
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
protected InvocationHandler h;
private Proxy() {
}
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
//调用有参的构造方法 传入invocatinghandler
return cons.newInstance(new Object[]{h});
}
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
return proxyClassCache.get(loader, interfaces);
}
}
- 内存中生成的代理类
public final class $Proxy0 extends Proxy
implements Person
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void listen()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("com.wh.Person").getMethod("listen", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
cglib动态代理
spring代理模式的使用和切换
默认当bean实现接口时使用jdk动态代理,没有实现时使用cglib
spring利用动态代理实现aop最主要的两个类:
- JdkDynamicAopProxy
- CglibAopProxy