Spring溫故而知新系列教程之AOP代理
AOP的概念
AOP:Aspect-Oriented Programming(面向切面編程),維基百科的解釋如下:Aspect是一種新的模塊化機(jī)制,用來描述分散在對(duì)象、類或者函數(shù)中的橫切關(guān)注點(diǎn),從關(guān)注點(diǎn)中分離出橫切關(guān)注點(diǎn)是面向切面的程序設(shè)計(jì)的核心概念。分離關(guān)注點(diǎn)使解決特定領(lǐng)域問題的代碼從業(yè)務(wù)邏輯中獨(dú)立出來,業(yè)務(wù)邏輯的代碼中不在含有針對(duì)特定領(lǐng)域問題的代碼的調(diào)用,業(yè)務(wù)邏輯同特定領(lǐng)域問題的關(guān)系通過切面來封裝、維護(hù),這樣原本分散在整個(gè)應(yīng)用程序中的變動(dòng)就可以很好地管理起來。從AOP的角度,應(yīng)用可以分為橫切關(guān)注點(diǎn)和業(yè)務(wù)邏輯代碼,實(shí)際開發(fā)中,這些橫切關(guān)注點(diǎn)往往會(huì)直接嵌入到業(yè)務(wù)邏輯代碼中,面向切面編程就是要解決把橫切關(guān)注點(diǎn)與業(yè)務(wù)邏輯相分離
實(shí)現(xiàn)方式:
Spring默認(rèn)使用 JDK 動(dòng)態(tài)代理作為AOP的代理,缺陷是目標(biāo)類的類必須實(shí)現(xiàn)接口,否則不能使用JDK動(dòng)態(tài)代理。如果需要代理的是類而不是接口,那么Spring會(huì)默認(rèn)使用CGLIB代理,關(guān)于兩者的區(qū)別:jdk動(dòng)態(tài)代理是通過java的反射機(jī)制來實(shí)現(xiàn)的,目標(biāo)類必須要實(shí)現(xiàn)接口,cglib是針對(duì)類來實(shí)現(xiàn)代理的,他的原理是動(dòng)態(tài)的為指定的目標(biāo)類生成一個(gè)子類,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但因?yàn)椴捎玫氖抢^承,所以不能對(duì)final修飾的類進(jìn)行代理。
JDK動(dòng)態(tài)代理
Jdk動(dòng)態(tài)代理是在程序運(yùn)行過程中,根據(jù)目標(biāo)類實(shí)現(xiàn)的接口來動(dòng)態(tài)生成代理類的class文件,使用主要涉及兩個(gè)類:
InvocationHandler接口: 它提供了一個(gè)invoke(Object obj,Method method, Object[] args)方法供實(shí)現(xiàn)者提供相應(yīng)的代理邏輯的實(shí)現(xiàn)。可以對(duì)實(shí)際的實(shí)現(xiàn)進(jìn)行一些特殊的處理其中參數(shù)
Object obj :被代理的目標(biāo)類
Method method: 需要執(zhí)行的目標(biāo)類的方法
Object[] args :目標(biāo)方法的參數(shù)
Proxy類:提供一個(gè)方法newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h)來獲得動(dòng)態(tài)代理類
示例代碼:
public interface OrderService {
public void createOrder();
}
public class OrderServiceImpl implements OrderService {
@Override
public void createOrder() {
System.out.println("creating order");
}
}
public class OrderLogger {
public void beforeCreateOrder(){
System.out.println("before create order");
}
public void afterCreateOrder(){
System.out.println("after create order");
}
}
package com.sl.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ServiceProxy implements InvocationHandler {
private Object targetClass;
private OrderLogger orderLogger;
public ServiceProxy(Object targetClass,OrderLogger orderLogger) {
this.targetClass = targetClass;
this.orderLogger = orderLogger;
}
//獲取代理
public Object GetDynamicProxy()
{
return Proxy.newProxyInstance(targetClass.getClass().getClassLoader(), //通過這個(gè)ClassLoader生成代理對(duì)象
targetClass.getClass().getInterfaces(),//代理類已實(shí)現(xiàn)的接口
this); //動(dòng)態(tài)代理調(diào)用方法是關(guān)聯(lián)的InvocationHandler,最終通過此InvocationHandler的invoke方法執(zhí)行真正的方法
}
//實(shí)現(xiàn)相應(yīng)的代理邏輯
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.orderLogger.beforeCreateOrder();
Object result= method.invoke(targetClass, args);
this.orderLogger.afterCreateOrder();
return result;
}
}
測(cè)試類:
package com.sl.aop;
import org.junit.Test;
public class AopTest {
@Test
public void Testdynamicproxy() {
OrderServiceImpl serviceImpl = new OrderServiceImpl();
OrderLogger logger = new OrderLogger();
OrderService service = (OrderService) new ServiceProxy(serviceImpl, logger).GetDynamicProxy();
service.createOrder();
}
}
運(yùn)行結(jié)果:

到這個(gè)其實(shí)還是有點(diǎn)困惑,Proxy.newProxyInstance()這個(gè)返回的是什么? Invoke方法在哪里調(diào)用的?我們看一下JDK源碼:看看DK動(dòng)態(tài)代理的過程是什么樣的:
根據(jù)源碼內(nèi)部的函數(shù)調(diào)用Proxy.newProxyInstance()->Proxy.getProxyClass0()->WeakCache.get() ,先定位到
WeakCache.class:
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
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);
}
}
}
}
可以看到函數(shù)return value; 而 V value = supplier.get(); 繼續(xù)往下讀可以發(fā)現(xiàn) supper=factory,實(shí)際上是一個(gè)Factory對(duì)象,那么繼續(xù)查看Factory.get()方法
public synchronized V get() { // serialize access
// re-check
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try {
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue<V> cacheValue = new CacheValue<>(value);
// try replacing us with CacheValue (this should always succeed)
if (valuesMap.replace(subKey, this, cacheValue)) {
// put also in reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
Return value;那么直接查看賦值語句:value = Objects.requireNonNull(valueFactory.apply(key, parameter));
valueFactory又什么鬼?
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
可以知道valueFactory是ProxyClassFactory類型對(duì)象,直接查看ProxyClassFactory. Apply()方法
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.
*/
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());
}
}
}
直接畫重點(diǎn):
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
調(diào)用ProxyGenerator.generateProxyClass最終動(dòng)態(tài)生成一個(gè)代理類,但是似乎并未找到何處調(diào)用了invoke方法;參考CSDN: http://chabaoo.cn/article/118935.htm這篇文章,嘗試將這個(gè)動(dòng)態(tài)生成的二進(jìn)制字節(jié)碼輸出到本地,并反編譯出來一看究竟,測(cè)試代碼如下:
public class AopTest {
@Test
public void Testdynamicproxy() {
OrderServiceImpl serviceImpl = new OrderServiceImpl();
OrderLogger logger = new OrderLogger();
OrderService service = (OrderService) new ServiceProxy(serviceImpl, logger).GetDynamicProxy();
service.createOrder();
//輸出動(dòng)態(tài)代理類字節(jié)碼
createProxyClassFile();
}
private static void createProxyClassFile(){
String name = "ProxyObject";
byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{OrderService.class});
FileOutputStream out =null;
try {
out = new FileOutputStream(name+".class");
System.out.println((new File("hello")).getAbsolutePath());
out.write(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null!=out) try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用java Decompiler工具將這個(gè)二進(jìn)制class文件反編譯查看:

具體動(dòng)態(tài)代理類ProxyObject.java:
import com.sl.aop.OrderService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class ProxyObject
extends Proxy
implements OrderService
{
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public ProxyObject(InvocationHandler paramInvocationHandler)
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
{
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 String toString()
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void createOrder()
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
{
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") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("com.sl.aop.OrderService").getMethod("createOrder", 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());
}
}
終于看到關(guān)于invoke的部分了:
public final void createOrder()
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
實(shí)際上動(dòng)態(tài)代理類繼承自Proxy,并且實(shí)現(xiàn)了目標(biāo)類繼承的接口,在createOrder方法中調(diào)用了invoke方法,實(shí)現(xiàn)了切面邏輯的植入,這里也回答了一個(gè)問題,為什么JDK動(dòng)態(tài)代理的目標(biāo)類必須是實(shí)現(xiàn)接口的,因?yàn)榇眍惼鋵?shí)是針對(duì)接口代理,而不是針對(duì)類來代理的,動(dòng)態(tài)代理類自己繼承自Proxy,Java也不允許多重繼承。動(dòng)態(tài)代理類和目標(biāo)類其實(shí)是各自實(shí)現(xiàn)了接口,代理類通過InvocationHandler.invoke實(shí)現(xiàn)對(duì)目標(biāo)類方法的調(diào)用。
CGLIB動(dòng)態(tài)代理
CGLIB代理是通過使用一個(gè)字節(jié)碼處理框架ASM,來轉(zhuǎn)換字節(jié)碼并生成新的類,并在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用,實(shí)現(xiàn)織如如橫切邏輯 ,效率上比使用反射技術(shù)的JDK動(dòng)態(tài)代理要高,但是由于CGLIB的原理是動(dòng)態(tài)為目標(biāo)類生成子類代理類,所以不能為聲明為final的方法進(jìn)行代理。其使用主要涉及兩個(gè)類:
MethodInterceptor接口:該接口提供一個(gè)方法intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3)主要用于攔截目標(biāo)類方法的調(diào)用
Object arg0, :被代理的目標(biāo)類
Method arg1, 委托方法
Object[] arg2, 方法參數(shù)
MethodProxy arg3 :代理方法的MethodProxy對(duì)象
Enhancer類:用于創(chuàng)建代理類
示例:
實(shí)現(xiàn)MethodInterceptor接口,代理類在調(diào)用方法時(shí),CGLIB會(huì)回調(diào)MethodInterceptor接口intercept方法,從而織入切面邏輯。
package com.sl.aop;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibServiceProxy implements MethodInterceptor {
private Object targetClass;
private OrderLogger orderLogger;
public CglibServiceProxy(Object targetClass,OrderLogger orderLogger) {
this.targetClass = targetClass;
this.orderLogger = orderLogger;
}
/**
* 創(chuàng)建代理對(duì)象
*
*/
public Object getInstance() {
Enhancer enhancer = new Enhancer();
//設(shè)置目標(biāo)類(需要被代理的類)
enhancer.setSuperclass(this.targetClass.getClass());
// 回調(diào)方法
enhancer.setCallback(this);
// 創(chuàng)建代理對(duì)象
return enhancer.create();
}
/**
* 攔截所有目標(biāo)類方法的調(diào)用
*
*/
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
orderLogger.beforeCreateOrder();
Object o1 = arg3.invokeSuper(arg0, arg2);
orderLogger.afterCreateOrder();
return o1;
}
}
測(cè)試方法:
public void Testdynamicproxy() {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
OrderServiceImpl serviceImpl = new OrderServiceImpl();
OrderLogger logger = new OrderLogger();
CglibServiceProxy proxy = new CglibServiceProxy(serviceImpl,logger);
//通過生成子類的方式創(chuàng)建代理類
OrderServiceImpl proxyImp = (OrderServiceImpl)proxy.getInstance();
proxyImp.createOrder();
}
結(jié)果:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");將cglib動(dòng)態(tài)代理類輸出到指定目錄,反編譯查看一下代理類真面目:
package com.sl.aop;
import com.sl.aop.OrderServiceImpl;
import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 extends OrderServiceImpl implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$createOrder$0$Method;
private static final MethodProxy CGLIB$createOrder$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.sl.aop.OrderServiceImpl$$EnhancerByCGLIB$$17779aa4");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$createOrder$0$Method = ReflectUtils.findMethods(new String[]{"createOrder", "()V"}, (var1 = Class.forName("com.sl.aop.OrderServiceImpl")).getDeclaredMethods())[0];
CGLIB$createOrder$0$Proxy = MethodProxy.create(var1, var0, "()V", "createOrder", "CGLIB$createOrder$0");
}
final void CGLIB$createOrder$0() {
super.createOrder();
}
public final void createOrder() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
var10000.intercept(this, CGLIB$createOrder$0$Method, CGLIB$emptyArgs, CGLIB$createOrder$0$Proxy);
} else {
super.createOrder();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null?false:((Boolean)var2).booleanValue();
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null?(String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy):super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null?0:((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null?var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy):super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -2138148221:
if(var10000.equals("createOrder()V")) {
return CGLIB$createOrder$0$Proxy;
}
break;
case -508378822:
if(var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1826985398:
if(var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if(var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if(var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public OrderServiceImpl$$EnhancerByCGLIB$$17779aa4() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var1 = (OrderServiceImpl$$EnhancerByCGLIB$$17779aa4)var0;
if(!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if(var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if(CGLIB$STATIC_CALLBACKS == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
上面的代碼可以看到代理類OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 繼承目標(biāo)類OrderServiceImpl并且實(shí)現(xiàn)了接口Factory,代理類中關(guān)于createorder生成了兩個(gè)方法CGLIB$createOrder$0和createOrder:
CGLIB$createOrder$0方法內(nèi)部直接調(diào)用目標(biāo)類的supper.createOrder
createOrder方法內(nèi)部首先盤點(diǎn)否實(shí)現(xiàn)了MethodInterceptor接口的callback,如果存在則調(diào)用MethodInterceptor接口攔截方法intercept,根據(jù)前面的實(shí)現(xiàn)intercept方法內(nèi)部實(shí)現(xiàn)了對(duì)目標(biāo)方法的調(diào)用Object o1 = arg3.invokeSuper(arg0, arg2) ,invokeSuper內(nèi)部實(shí)際上是直接調(diào)用的代理類的CGLIB$createOrder$0()方法,最終調(diào)用了目標(biāo)類createOrder。
兩種代理對(duì)比
JDK動(dòng)態(tài)代理:
代理類與委托類實(shí)現(xiàn)同一接口,主要是通過代理類實(shí)現(xiàn)InvocationHandler并重寫invoke方法來進(jìn)行動(dòng)態(tài)代理的,在invoke方法中將對(duì)方法進(jìn)行增強(qiáng)處理 優(yōu)點(diǎn):不需要硬編碼接口,代碼復(fù)用率高,缺點(diǎn):只能夠代理實(shí)現(xiàn)了接口的委托類
CGLIB動(dòng)態(tài)代理:
代理類將委托類作為自己的父類并為其中的非final委托方法創(chuàng)建兩個(gè)方法,一個(gè)是與委托方法簽名相同的方法,它在方法中會(huì)通過super調(diào)用委托方法;另一個(gè)是代理類獨(dú)有的方法。在代理方法中,它會(huì)判斷是否存在實(shí)現(xiàn)了MethodInterceptor接口的對(duì)象,若存在則將調(diào)用intercept方法對(duì)委托方法進(jìn)行代理 優(yōu)點(diǎn):可以在運(yùn)行時(shí)對(duì)類或者是接口進(jìn)行增強(qiáng)操作,且委托類無需實(shí)現(xiàn)接口,缺點(diǎn):不能對(duì)final類以及final方法進(jìn)行代理
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Maven Spring jar包啟動(dòng)報(bào)錯(cuò)問題解決方案
maven 編譯jar包,放在linux服務(wù)器啟動(dòng)不起來,提示:xxxx-0.0.1-SNAPSHOT.jar中沒有主清單屬性,接下來通過本文給大家分享問題原因及解決方案,感興趣的朋友跟隨小編一起看看吧2023-10-10
IntelliJ IDEA 如何徹底刪除項(xiàng)目的步驟
本篇文章主要介紹了IntelliJ IDEA 如何徹底刪除項(xiàng)目的步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11
詳解Spring Cloud Alibaba Sidecar多語言微服務(wù)異構(gòu)
這篇文章主要介紹了詳解Spring Cloud Alibaba Sidecar多語言微服務(wù)異構(gòu),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
java實(shí)現(xiàn)隨機(jī)輸出300題四則運(yùn)算
本文主要介紹了java實(shí)現(xiàn)隨機(jī)輸出300題四則運(yùn)算實(shí)例,具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-03-03
Java字節(jié)碼增強(qiáng)技術(shù)知識(shí)點(diǎn)詳解
在本篇文章里小編給大家整理的是一篇關(guān)于Java字節(jié)碼增強(qiáng)技術(shù)知識(shí)點(diǎn)詳解內(nèi)容,有興趣的朋友可以跟著學(xué)習(xí)下。2021-08-08
SpringMVC?@RequestMapping注解屬性詳細(xì)介紹
通過@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
Java中遇到的For?input?string問題解決辦法
這篇文章主要給大家介紹了關(guān)于Java中遇到的For?input?string問題的解決辦法,如果出現(xiàn)這樣的異常報(bào)錯(cuò),是指的數(shù)據(jù)轉(zhuǎn)換時(shí)出錯(cuò),文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
Spring?Cloud?OpenFeign模版化客戶端搭建過程
OpenFeign是一個(gè)顯示聲明式的WebService客戶端。使用OpenFeign能讓編寫Web Service客戶端更加簡(jiǎn)單,這篇文章主要介紹了Spring?Cloud?OpenFeign模版化客戶端,需要的朋友可以參考下2022-06-06
spring boot攔截器實(shí)現(xiàn)IP黑名單實(shí)例代碼
本篇文章主要介紹了spring boot攔截器實(shí)現(xiàn)IP黑名單實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04

