一、jdk 动态代理 和 cglib动态代理 简单介绍
1.jdk动态代理
public interface AService {
public String serviceA(String param);
public String serviceAA(String param);
}
public interface BService {
public String serviceB(String param);
public String serviceBB(String param);
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JdkCustomInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if(method.equals(AService.class.getMethod("serviceA" , String.class))){
// 在这里可以写 当我们把代理当作 AService 的实现子类,调用 serviceA 方法时
// 我们要执行的代码,这里我们姑且就简单打印,并返回一个值
System.out.println("JdkCustomInvocationHandler 开始处理 com.fll.start.dynamic_proxy.jdk.AService.serviceA 方法");
return "JdkCustomInvocationHandler 处理 com.fll.start.dynamic_proxy.jdk.BService.serviceA 的结果";
}else if(method.equals(BService.class.getMethod("serviceB", String.class))){
// 在这里可以写 当我们把代理当作 BService 的实现子类,调用 serviceB 方法时
// 我们要执行的代码,这里我们姑且就简单打印,并返回一个值
System.out.println("JdkCustomInvocationHandler 开始处理 com.fll.start.dynamic_proxy.jdk.BService.serviceB 方法");
return "JdkCustomInvocationHandler 处理 com.fll.start.dynamic_proxy.jdk.BService.serviceB 的结果";
}else {
return "暂时对该方法没有处理逻辑";
}
}
}
这里总结下jdk动态代理的特点:
1.可以不需要实现类,直接对接口进行代理
2.创建代理对象时返回的类型时Object,但是可以将其强转为任何一个它所代理的接口类型
因为生成的代理对象是它所代理的所有接口的实现类
3.当我们将代理对象强转为它所代理的接口类型进行方法调用时,所有的调用都会回调到InvocationHandler 对象的 invoke 方法,在回调 invoke 方法的参数中有我们调用的方法对象 Method method,和调用时所传递的所有参数Object[] objects,Object o就是代理对象本身
4.关于这几个参数的注意点
1.不能在 invoke 方法中将代理对象强转为它所代理的某一个接口,然后调用其方法,这 样会形成递归调用,造成栈内存溢出
2.如果没有所代理的接口的真正实现类,不可以通过反射的方法调用该方法,因为通过 反射的方式,Method.invoke() 方法进行调用时,需要传递真正实现了该接口的实现类的一个 对象,这里的Object o对象虽然也是接口的实现类的对象,但是不能传递 o ,如果过传递 o,还是相当于调用了代理对象的方法,也会形成递归调用。
3.要想让代理对象调用不同的方法时,分别执行我们想要的逻辑,只能在 invoke 方法的 回调中通过判断 Method method 对象的不同,执行不同业务逻辑
5.这样的的代理方式没啥实际意义,只是把对所有接口方法的调用全部回调到了 InvocationHandler.invoke() 方法中,在invoke中进行分别实现,会造成代码冗长杂乱
接下来常规用法
public class AServiceImpl implements AService{
@Override
public String serviceA(String param){
System.out.println("AServiceImpl 开始执行 serviceA,param=" + param);
return "AServiceImpl.serviceA 处理的结果";
}
@Override
public String serviceAA(String param) {
System.out.println("AServiceImpl 开始执行 serviceAA,param=" + param);
return "AServiceImpl.serviceAA 处理的结果";
}
}
public class BServiceImpl implements BService{
@Override
public String serviceB(String param){
System.out.println("BServiceImpl 开始执行 serviceB,param=" + param);
return "BServiceImpl.serviceB 处理的结果";
}
@Override
public String serviceBB(String param) {
System.out.println("BServiceImpl 开始执行 serviceBB,param=" + param);
return "BServiceImpl.serviceBB 处理的结果";
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JdkCustomInvocationHandler1 implements InvocationHandler {
private AService aService;
private BService bService;
public JdkCustomInvocationHandler1(AService aService , BService bService){
this.aService = aService;
this.bService = bService;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if(method.equals(AService.class.getMethod("serviceA" , String.class))){
System.out.println(String.format("执行%s前置加强逻辑" , aService.getClass() +"."+ method.getName()));
Object retVal = method.invoke(this.aService , objects);
System.out.println(String.format("执行%s后置加强逻辑" , aService.getClass() +"."+ method.getName()));
return retVal + "(也可以被代理对象再加工)";
}else if(method.equals(BService.class.getMethod("serviceB", String.class))){
System.out.println(String.format("执行%s前置加强逻辑" , bService.getClass() +"."+ method.getName()));
Object retVal = method.invoke(this.bService , objects);
System.out.println(String.format("执行%s后置加强逻辑" , bService.getClass() +"."+ method.getName()));
return retVal + "(也可以被代理对象再加工)";
}else {
return "暂时对该方法没有处理逻辑";
}
}
}
public class JdkDynamicProxyTest1 {
public static void main(String[] args) throws IOException {
ClassLoader classLoader = JdkDynamicProxyTest1.class.getClassLoader();
Class[] interfaces = {AService.class, BService.class};
AService aService = new AServiceImpl();
BService bService = new BServiceImpl();
JdkCustomInvocationHandler1 jdkCustomInvocationHandler
= new JdkCustomInvocationHandler1(aService , bService);
AService aServiceProxy = (AService) Proxy.newProxyInstance(classLoader, interfaces, jdkCustomInvocationHandler);
String test = aServiceProxy.serviceA("AService");
System.out.println(test);
System.out.println();
BService bServiceProxy = (BService) Proxy.newProxyInstance(classLoader , interfaces , jdkCustomInvocationHandler);
String test1 = bServiceProxy.serviceB("BService");
System.out.println(test1);
}
}
运行结果:
执行class com.fll.start.dynamic_proxy.jdk.AServiceImpl.serviceA前置加强逻辑
AServiceImpl 开始执行 serviceA,param=AService
执行class com.fll.start.dynamic_proxy.jdk.AServiceImpl.serviceA后置加强逻辑
AServiceImpl.serviceA 处理的结果(也可以被代理对象再加工)
执行class com.fll.start.dynamic_proxy.jdk.BServiceImpl.serviceB前置加强逻辑
BServiceImpl 开始执行 serviceB,param=BService
执行class com.fll.start.dynamic_proxy.jdk.BServiceImpl.serviceB后置加强逻辑
BServiceImpl.serviceB 处理的结果(也可以被代理对象再加工)
这次的特点:
1.所代理的接口本来就有自己的实现类
2.调用所代理的接口的方法时,最终都会在 InvocationHandler.invoke() 方法中通过反射 的方式调用到接口实现类对象的对应方法上,只不过我们可以在调用实现类方法之前或者之 后执行额外的逻辑,进行加强,也可以对实现类返回的结果进行再加工
其实这种方式才是代理模式要达到的真正目的,本来就有实现好的功能,而且代码运行稳定,或者说一个黑盒子,我们只知道其功能和参数,这些情况下,我们想要对原本的功能或者黑盒子进行加强,但是又不想修改原来代码逻辑,所以就可以通过代理,在原来的功能之上 ,进行额外的加强处理
通过jdk源码,看看代理对象是如何创建的
java.lang.reflect.Proxy#newProxyInstance
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
*
* <p>{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
* {@code Proxy.getProxyClass} does.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
* @throws SecurityException if a security manager, <em>s</em>, is present
* and any of the following conditions is met:
* <ul>
* <li> the given {@code loader} is {@code null} and
* the caller's class loader is not {@code null} and the
* invocation of {@link SecurityManager#checkPermission
* s.checkPermission} with
* {@code RuntimePermission("getClassLoader")} permission
* denies access;</li>
* <li> for each proxy interface, {@code intf},
* the caller's class loader is not the same as or an
* ancestor of the class loader for {@code intf} and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to {@code intf};</li>
* <li> any of the given proxy interfaces is non-public and the
* caller class is not in the same {@linkplain Package runtime package}
* as the non-public interface and the invocation of
* {@link SecurityManager#checkPermission s.checkPermission} with
* {@code ReflectPermission("newProxyInPackage.{package name}")}
* permission denies access.</li>
* </ul>
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
* {@code null}
*/
@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 对象
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 这里的private static final Class<?>[] constructorParams =
// {InvocationHandler.class };
// 通过代理类的 Class 对象获取参数为 InvocationHandler 对象的构造器对象
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);
}
}
java.lang.reflect.Proxy#getProxyClass0
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
// 如果被指定的类加载器定义好的,实现了指定接口的代理类 Class 对象已经存在了
// 那就简单的返回缓存中的备份,相反如果不存在,就得通过ProxyClassFactory创建
// 代理类的 Class 对象,并放入缓存中
return proxyClassCache.get(loader, interfaces);
}
java.lang.reflect.WeakCache#get
/**
* Look-up the value through the cache. This always evaluates the
* {@code subKeyFactory} function and optionally evaluates
* {@code valueFactory} function if there is no entry in the cache for given
* pair of (key, subKey) or the entry has already been cleared.
*
* @param key possibly null key
* @param parameter parameter used together with key to create sub-key and
* value (should not be null)
* @return the cached value (never null)
* @throws NullPointerException if {@code parameter} passed in or
* {@code sub-key} calculated by
* {@code subKeyFactory} or {@code value}
* calculated by {@code valueFactory} is null.
*/
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
//
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
// 生成代理类Class对象的主要逻辑在 subKeyFactory.apply(key, parameter)
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
java.lang.reflect.Proxy.ProxyClassFactory#apply
/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
* 生成代理类,我们看到生成代理类Class对象需要两部
* 1.生成一个字节数组,其实等价于我们通过.class文件创建Class对象的时候,把.class文件
* 加载进内存,放到一个字节数组中
* 2.通过 defineClass0() 方法把字节数组解析为一个Class对象
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
我们看到可以通过以下代码生成一个等价于.class文件的字节数组,那我们把生成的这个字节数组输出到一个文件,是不是就相当于得到了这个代理类的 .class 文件了
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
import sun.misc.ProxyGenerator;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ProxyGeneratorTest {
public static void main(String[] args) throws IOException {
ClassLoader classLoader = JdkDynamicProxyTest1.class.getClassLoader();
Class[] interfaces = {AService.class, BService.class};
AService aService = new AServiceImpl();
BService bService = new BServiceImpl();
JdkCustomInvocationHandler1 jdkCustomInvocationHandler
= new JdkCustomInvocationHandler1(aService , bService);
Object proxyInstance = Proxy.newProxyInstance(classLoader, interfaces, jdkCustomInvocationHandler);
byte[] bytes = ProxyGenerator.generateProxyClass(proxyInstance.getClass().getSimpleName(), interfaces);
Files.write(Paths.get("D:/springboot-demo/study-spring/src/main/java/com/fll/start/dynamic_proxy/jdk/" + proxyInstance.getClass().getSimpleName() + ".class") , bytes);
}
}
以下是使用idea将生成的.class文件反编译之后得到的源码
import com.fll.start.dynamic_proxy.jdk.AService;
import com.fll.start.dynamic_proxy.jdk.BService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements AService, BService {
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m6;
private static Method m3;
private static Method m0;
private static Method m5;
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 serviceA(String var1) throws {
try {
return (String)super.h.invoke(this, m4, 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 String serviceBB(String var1) throws {
try {
return (String)super.h.invoke(this, m6, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String serviceAA(String var1) throws {
try {
return (String)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
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);
}
}
public final String serviceB(String var1) throws {
try {
return (String)super.h.invoke(this, m5, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("com.fll.start.dynamic_proxy.jdk.AService").getMethod("serviceA", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m6 = Class.forName("com.fll.start.dynamic_proxy.jdk.BService").getMethod("serviceBB", Class.forName("java.lang.String"));
m3 = Class.forName("com.fll.start.dynamic_proxy.jdk.AService").getMethod("serviceAA", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m5 = Class.forName("com.fll.start.dynamic_proxy.jdk.BService").getMethod("serviceB", Class.forName("java.lang.String"));
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
这里注意最好用 jdk1.8,在jdk11 中,这个方法就不是public了,测试调用的话比较麻烦
可以看到这里的代理类 除了实现了 我们要代理的接口 AService, BService之外还结成了java.lang.reflect.Proxy,我们使用代理类的构造器创建代理对象时,所传的 构造器参数InvocationHandler 就是通过 super(InvocationHandler) 传到了java.lang.reflect.Proxy
2.cglib动态代理
二、Spring中的 三个重要的概念 Advice Advisor Advised
1.Advice
2.Advisor
3.Advised
三、ProxyFactory 类的继承结构,以及每一层中实现的功能
四、AopProxyFactory的默认实现类DefaultAopProxyFactory的介绍
五、Spring 中的 InvocationHandler --- JdkDynamicAopProxy
六、AdvisedSupport 中 getInterceptorsAndDynamicInterceptionAdvice 详解
七、AdvisorChainFactory 的默认实现类 DefaultAdvisorChainFactory
八、AdvisorAdapterRegistry 的 默认实现类 DefaultAdvisorAdapterRegistry
九、简单介绍 Interceptor
十、详细介绍 MethodInterceptor
十一、如何通过 MethodInterceptor 几个实现类实现 Advice 的顺序调用
AdvisorChainFactory 的默认实现类 DefaultAdvisorChainFactory