Концепция AOP
AOP: Аспективное программирование (программирование, ориентированное на раздел), Википедия объясняет это следующим образом: аспект-это новый модульный механизм, используемый для описания проблем поперечного сечения, разбросанных по объектам, классам или функциям. Отделение проблем поперечного сечения от проблем является основной концепцией ориентированного на касательно программирования. Разделение фокуса делает код, который решает конкретные проблемы домена независимыми от бизнес -логики. Код бизнес -логики не содержит вызовов для кода для конкретных задач домена. Взаимосвязь между бизнес -логикой и конкретными проблемами домена инкапсулируется и поддерживается через разделы, так что изменения, которые первоначально разбросаны по всему приложению, могут быть хорошо управлялись. С точки зрения AOP, приложения можно разделить на поперечные проблемы и код бизнес-логики. В реальной разработке эти проблемы поперечного сечения часто непосредственно встроены в код бизнес-логики. Программирование, ориентированное на лицо, предназначено для решения проблемы отделения проблем поперечного сечения от бизнес-логики.
Метод реализации:
Spring использует JDK Dynamic Proxy в качестве прокси AOP по умолчанию. Недостаток заключается в том, что целевой класс должен реализовать интерфейс, в противном случае динамический прокси JDK не может быть использован. Если класс является классом, а не интерфейсом, Spring будет использовать Cglib Proxy по умолчанию. Что касается разницы между двумя: динамический прокси JDK реализуется с помощью механизма отражения Java, целевой класс должен реализовать интерфейсы, а CGlib реализует прокси для классов. Его принцип - динамически генерировать подкласс для указанного целевого класса и переопределить улучшение реализации метода, но поскольку используется наследование, окончательный модифицированный класс не может быть доверен.
JDK Dynamic Proxy
JDK Dynamic Proxy Динамически генерирует файлы классов классов прокси на основе интерфейса, реализованного целевым классом во время операции программы. Использование в основном включает в себя два класса:
InvocationHandler Interface: он предоставляет метод invoke(Object obj,Method method, Object[] args) для реализаторов для предоставления соответствующей реализации прокси -логики. Некоторая специальная обработка может быть выполнена на фактической реализации, а параметры
Объект OBJ: целевой класс, который является доверенным лицом
Метод метода: метод целевого класса, который необходимо выполнить
Object [] args: параметры целевого метода
Класс прокси: предоставьте метод newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h) для получения динамического класса прокси -сервера
Пример кода:
Public Interface Orderservice {public void createorder (); } открытый класс ordersersImpl реализует orderservice {@override public void createorder () {system.out.println («Создание порядка»); }} public class orderlogger {public void beforeCreateEroder () {System.out.println («Перед созданием порядка»); } public void -efprecreateEroder () {System.out.println ("После создания порядка"); }} пакет com.sl.aop; import java.lang.reflect.invocationHandler; импорт java.lang.reflect.method; импорт java.lang.reflect.proxy; Общедоступный класс ServiceProxy реализует vlocationHandler {private Object TargetClass; Частный OrderLogger OrderLogger; Public ServiceProxy (Object TargetClass, OrderLogger OrderLogger) {this.TargetClass = TargetClass; this.orderlogger = orderlogger; } // Получить Proxy Public Object getDynamicProxy () {return proxy.newproxyinstance (targetClass.getClass (). GetClassloader (), // Создать объект Proxy через этот класс targetClass.getClass (). GetInterfaces (), // интерфейс, реализованный класс Proxy); // Метод динамического прокси -вызова является соответствующим vlocationHandler, и, наконец, выполняет реальный метод с помощью метода Invoke настоящего vocationHandler} // Реализация соответствующей прокси -логики @Override public Object Invoke (Object Proxy, метод, объект [] args) бросает Throwable {this.orderlogger.beforeCreeToRoder (); Object result = method.invoke (TargetClass, Args); this.orderlogger.afterCreateOrder (); результат возврата; }}Тестовый класс:
пакет 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 (); }}Результаты работы:
Я на самом деле немного смущен, когда достигаю этой точки. Что возвращает Proxy.newProxyInstance() ? Где называется метод вызовов? Давайте посмотрим на исходный код JDK: посмотрите, как выглядит процесс DK Dynamic Proxy:
Call Proxy.newProxyInstance()->Proxy.getProxyClass0()->WeakCache.get() в соответствии с функцией внутри исходного кода и сначала найдите его
SleedCache.class:
public v get (k key, p parameter) {objects.requirenonnull (параметр); ensungestaleentries (); Object CacheKey = cacheKey.valueof (ключ, опровержение); // лениво установить 2 -й уровень значений уровня для конкретного cachekey concurrentMap <объект, поставщик <v >> valuesmap = map.get (cachekey); if (valuesmap == null) {coundrentMap <объект, поставщик <v >> oldvaluesmap = map.putifabsent (cachekey, valuesmap = new concurrenthashmap <> ()); if (oldvaluesmap! = null) {valuesmap = oldvaluesmap; }} // Создать подкей и получить возможный поставщик <v>, хранящийся с помощью этого // подкиата из объекта Valuesmap subkey = objects.requirenonlonull (subkeyfactory.apply (key, parameter)); Поставщик <v> поставщик = valuemap.get (subkey); Заводская фабрика = null; while (true) {if (поставщик! = null) {// Поставщик может быть фабрикой или Cachevalue <v> vance v value = valure.get (); if (value! = null) {return value; }} // else Поставщик в кэше // или поставщик, который возвращал нулевый (может быть очищенным Cachevalue // или фабрикой, которая не была успешной в установке Cachevalue) // Lazerly Construct factory if (factory == null) {factory = новый завод (ключ, параметр, подкюль } if (поставщик == null) {поставщик = valuesmap.putifabsent (subkey, factory); if (поставщик == null) {// успешно установлен заводской поставщик = завод; } // else повторить с победным поставщиком} else {if (valuesmap.replace (subkey, поставщик, завод)) {// успешно заменен // очистить CacheEntry / Unsuccessful Factory // с нашим заводским поставщиком = Factory; } else {// повторно с текущим поставщиком поставщика поставщика = valuesmap.get (subkey); }}}} Вы можете увидеть возвращаемое значение функции; и V value = supplier.get(); Продолжайте читать его и обнаружите, что Supper = Factory на самом деле является заводским объектом, поэтому продолжайте просматривать метод Factory.get()
public Synchronized v get () {// serialize access // перепроверить поставщик <v> поставщик = valuesmap.get (subkey); Если (поставщик! = это) {// что -то изменилось, пока мы ждали: // может быть то, что нас заменили CacheValue // или были удалены из -за сбоя -> // возврата NULL, чтобы сигнализировать sleadcache.get (), чтобы повторно // возврат цикла NULL; } // else ell us (поставщик == это) // Создать новое значение vall = null; try {value = objects.requirenonlonull (valuefactory.apply (key, parameter)); } наконец {if (value == null) {// Удалить нас при сбое значениям. }} // Единственный путь для достижения здесь-это не нулевое значение Assert! = NULL; // значение обертывания с помощью CacheValue (SleedReference) CacheValue <v> cachevalue = new Cachevalue <> (значение); // Попробуйте заменить нас на CacheValue (это всегда должно быть успешным) if (valuesmap.replace (subkey, this, cachevalue)) {// Поместить также в reversemap reversemap.put (cachevalue, boolean.true); } else {бросить новый AssertionError ("не должен быть здесь"); } // успешно заменил нас новым CacheValue -> вернуть значение // обернутое его возвратным значением; } Возвращаемое значение; Затем напрямую просмотреть оператор назначения: value = Objects.requireNonNull(valueFactory.apply(key, parameter));
Что, черт возьми, является ценным?
Public SleaseCache (Bifunction <K, P,?> SubkeyFactory, Bifunction <K, P, V> valueFactory) {this.SubkeyFactory = objects.Requirenonnull (subkeyFactory); this.valuefactory = objects.requirenonlull (valueFactory); } private static final sledcache <classloader, class <?> [], class <? >> proxyclasscache = new SleadCache <> (new KeyFactory (), New ProxyClassFactory ()); Вы можете знать, что valueFactory - это объект типа ProxyClassCASCASCEST, и напрямую просмотреть ProxyClassFactory. Apply() Метод
public class <?> Apply (ClassLoader Loader, Class <?> [] Интерфейсы) {map <class <?>, boolean> interfaceset = new IdentityHashmap <> (интерфейсы.length); Для (класс <?> Intf: Interfaces) { / * * Убедитесь, что загрузчик класса разрешает имя этого * интерфейса к одному и тому же объекту класса. */ Class <?> InterfaceClass = null; try {interfaceclass = class.forname (intf.getName (), false, loader); } catch (classnotfoundexception e) {} if (interfaceclass! = intf) {бросить новый allosalargumentException (intf + "не видно из загрузчика класса"); } / * * Убедитесь, что объект класса фактически представляет интерфейс *. */ if (! interfaceclass.isInterface ()) {бросить новый allosalargumentException (enterfaceclass.getName () + "не является интерфейсом"); } / * * Убедитесь, что этот интерфейс не является дубликатом. */ if (interfaceset.put (interfaceclass, boolean.true)! = null) {throw new allodalargumentException ("повторный интерфейс:" + enterfaceclass.getName ()); }} String proxypkg = null; // Пакет для определения класса прокси в int accessflags = modifier.public | Modifier.final; / * * Запишите пакет непубличного прокси-интерфейса, чтобы * Proxy Class был определен в том же пакете. Убедитесь, что * все непубличные прокси-интерфейсы находятся в одном пакете. */ for (class <?> intf: интерфейсы) {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)) {бросить new allogalargumentException («Непубличные интерфейсы из разных пакетов»); }}}} if (proxypkg == null) {// Если нет непубличных прокси-интерфейсов, используйте com.sun.proxy package proxypkg = Refertutil.proxy_package + "."; } / * * Выберите имя для создания класса прокси. */ long num = nextUniqueNumber.getAndIncrement (); String proxyname = proxypkg + proxyclassamprefix + num; / * * Сгенерировать указанный класс прокси. */ byte [] proxyclassfile = proxygenerator.generateproxyclass (proxyname, интерфейсы, AccessFlags); try {return deciplasclass0 (Loader, ProxyName, ProxyClassFile, 0, proxyClassfile.length); } catch (classformaterror e) { / * * a classformaterror здесь означает, что (за исключением ошибок в коде генерации класса *). Был какой -то другой * недействительный аспект аргументов, предоставленных в создание прокси * (например, ограничения виртуальной машины *). */ бросить новое allogalargumentException (e.toString ()); }}}Напрямую нарисуйте ключевые моменты:
byte [] proxyclassfile = proxygenerator.generateproxyclass (proxyname, интерфейсы, AccessFlags); return decipleclass0 (Loader, ProxyName, ProxyClassFile, 0, ProxyClassFile.length);
Вызов ProxyGenerator.generateProxyClass наконец, динамически генерирует класс прокси, но кажется, что нигде не называется Invoke; Обратитесь к статье CSDN: //www.vevb.com/article/118935.htm, попробуйте вывести динамически сгенерированный двоичный байт -код локально и декомпилировать ее, чтобы увидеть, что это такое. Тестовый код заключается в следующем:
открытый класс aoptest {@test public void testdynamicproxy () {orderserviceimpl serviceImpl = new orderserviceImpl (); OrderLogger logger = new OrderLogger (); Orderservice Service = (Orderservice) New ServiceProxy (ServiceImpl, Logger) .getDynamicProxy (); Service.createOrder (); // Вывод динамического класса прокси -класса ByteCode CreateProxyClassFile (); } private static void createProxyClassfile () {string name = "proxyObject"; byte [] data = proxygenerator.generateproxyclass (имя, новый класс [] {orderservice.class}); FileOutputStream OUT = null; try {out = new FileOutputStream (name+". Class"); System.out.println ((новый файл ("hello")). Getabsolutepath ()); out.write (data); } catch (filenotFoundException e) {e.printstackTrace (); } catch (ioException e) {e.printstackTrace (); } наконец {if (null! = out) попробуйте {out.close (); } catch (ioException e) {e.printstackTrace (); }}}}}}Используйте инструмент Java Decropiler, чтобы декомпилировать этот двоичный файл класса:
Конкретный динамический прокси -класс ProxyObject.java:
Импорт com.sl.aop.orderservice; import java.lang.reflect.invocationHandler; импорт java.lang.reflect.method; импорт java.lang.reflect.proxy; импорт java.lang.reflect.undeclaredThrowableException; public proxyobject extends usemobject usemesservexexexexceptexception; public proxyobject extends raderservice rescraceableexceptexceptable; частный статический метод M2; частный статический метод M3; частный статический метод M0; public proxyObject (vlocationHandler paraminVocationHandler) {super (paraminvocationHandler); } public final Boolean Equals (Object ParamoBject) {try {return ((boolean) this.h.invoke (this, m1, new object [] {paramobject})). BooleanValue (); } catch (ошибка | runtimeexception localerror) {throw LocalError; } catch (throwable localthrowable) {бросить новый UndeclaredThrowableException (localThrowable); }} public final String toString () {try {return (string) this.h.invoke (this, m2, null); } catch (ошибка | runtimeexception localerror) {throw LocalError; } catch (throwable localthrowable) {бросить новый UndeclaredThrowableException (localThrowable); }} public final void createorder () {try {this.h.invoke (this, m3, null); возвращаться; } catch (ошибка | runtimeexception localerror) {throw LocalError; } catch (throwable localthrowable) {бросить новый UndeclaredThrowableException (localThrowable); }} public final int hashcode () {try {return ((integer) this.h.invoke (this, m0, null)). intvalue (); } catch (ошибка | runtimeexception localerror) {throw LocalError; } catch (throwable localthrowable) {бросить новый 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", новый класс [0]); m3 = class.forname ("com.sl.aop.orderservice"). getmethod ("createorder", новый класс [0]); m0 = class.forname ("java.lang.object"). getmethod ("hashcode", новый класс [0]); возвращаться; } catch (nosuchmethodexception localnosuchmethodexception) {бросить новый nosuchmethoderror (localnosuchmethodexception.getmessage ()); } catch (classnotfoundexception localclassnotfoundexception) {бросить новый noclassdeffounderror (localclassnotfoundexception.getmessage ()); }}Наконец -то увидел часть о Anloke:
public final void createorder () {try {this.h.invoke (this, m3, null); возвращаться; } catch (ошибка | runtimeexception localerror) {throw LocalError; } catch (throwable localthrowable) {бросить новый UndeclaredThrowableException (localThrowable); }}Фактически, класс динамического прокси наследует от прокси и реализует интерфейс, унаследованный целевым классом. Метод вызова вызывается в методе Createorder, который реализует имплантацию логики секции. Здесь мы также отвечаем на вопрос, почему целевой класс динамического прокси JDK должен реализовать интерфейс, потому что класс прокси на самом деле направлен на интерфейс, а не на класс. Динамический класс прокси наследуется от прокси, а Java не допускает множественного наследства. Динамический класс прокси и целевой класс фактически реализует интерфейсы соответственно. Класс прокси реализует призыв к методу целевого класса через vocationhandler.invoke.
CGLIB Dynamic Proxy
Прокси CGLIB использует структуру обработки байт-кодов для преобразования байт-кодов и генерации новых классов, а также использует методы перехвата методов в подклассах для перехвата всех методов родительского класса для реализации логики перекрестного выреза, что более эффективно, чем динамический прокси JDK с использованием технологии отражения. Однако, поскольку принцип CGlib заключается в динамически генерировать классы прокси -сервера подкласса для целевого класса, его нельзя доверенное для методов, объявленных окончательными. Его использование в основном включает в себя две категории:
Интерфейс MethodInterceptor: этот интерфейс предоставляет метод intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) в основном используемый для перехвата методов вызова целевого класса.
Object Arg0,: целевой класс, который прокси -прокси
Метод arg1, метод делегата
Object [] arg2, параметры метода
MethodProxy Arg3: MethodProxy объект прокси -метода
Класс Enhancer: используется для создания прокси -класса
Пример:
Реализуйте интерфейс MethodInterceptor. Когда класс прокси вызывает метод, CGlib вызовет метод интерфейса интерфейса MethodInterceptor, тем самым сдвигая логику поверхности.
пакет com.sl.aop; import java.lang.reflect.method; import org.springframework.cglib.proxy.enhancer; импорт org.springframework.cglib.proxy.methodinterceptor; import.springframework.cglib.proxyproxyproxpempersementsementsementsementsementsementsemesserments.cglib.proxyproxpoxementy.cgliby.proxeproxy.methodinterceptor; {Private Object TargetClass; Частный OrderLogger OrderLogger; public cglibServiceProxy (объект TargetClass, OrderLogger OrderLogger) {this.TargetClass = targetClass; this.orderlogger = orderlogger; } / *** Создать прокси -объект** / public Object getInstance () {Enhancer Enhancer = new Enhancer (); // Установить целевой класс (класс, который должен быть проксирован) Enhancer.setSuperClass (this.TargetClass.getClass ()); // метод обратного вызова Enhancer.setCallback (this); // Создать доверенный объект return Enhance.create (); } / *** Intercept All Target Class Methods** / @Override Public Object Intercept (Object arg0, Method arg1, object [] arg2, methodproxy arg3) бросает throwable {orderlogger.beforeeCreateeRoder (); Объект O1 = arg3.invokesuper (arg0, arg2); orderLogger.afterCreateOrder (); вернуть O1; }}Метод испытаний:
public void testDynamicProxy () {System.SetProperty (DebuggingClassWriter.debug_location_property, "d: // class"); Orderserviceimpl serviceImpl = new OrderserServiceImpl (); OrderLogger logger = new OrderLogger (); Cglibserviceproxy proxy = new cglibserviceproxy (ServiceImpl, Logger); // Создать класс прокси, генерируя подклассы orderserviceimpl proxyimp = (orderserviceimpl) proxy.getinstance (); proxyimp.createOrder (); }результат:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://class"); Вывод динамического прокси -класса CGLIB в указанный каталог, декомпилировать и проверить истинную поверхность класса прокси:
пакет com.sl.aop; import com.sl.aop.orderserviceimpl; import java.lang.reflect.method; import org.springframework.cglib.core.reflectutils; import org.springframework.cglib.core.signuret; import org.spramework.cliby.prox org.springframework.cglib.proxy.factory; import org.springframework.cglib.proxy.methodinterceptor; импорт org.springframework.cglib.proxy.methodproxy; public class orderserviceimpl $ $ Cglib $ bound; общественный статический объект cglib $ factory_data; частная статическая конечная нитока Cglib $ think_callbacks; Частный статический окончательный обратный вызов [] cglib $ static_callbacks; Частный метод Interceptor cglib $ callback_0; частный статический объект cglib $ callback_filter; частный статический окончательный метод CGLIB $ CREATERORD $ 0 $ Метод; Частный статический окончательный метод прокси CGLIB $ CREATERORD $ 0 $ прокси; частный статический конечный объект [] cglib $ emptyargs; Частный статический окончательный метод cglib $ равна $ 1 $ Метод; Частный статический окончательный метод Proxy Cglib $ Equals $ 1 $ прокси; частный статический метод CGLIB $ TOSTRING $ 2 $ Метод; Частный статический окончательный метод Прокси -прокси -сервер; частный статический метод CGLIB $ HASHCODE $ 3 $ Метод; Частный статический окончательный метод Прокси -прокси -сервера $ 3 $ 3 $; Частный статический окончательный метод, клон $ 4 $ Метод; Частный статический окончательный метод Прокси -прокси -сервера Cglib $ 4 $; static void cglib $ statichook1 () {cglib $ thread_callbacks = new Threadlocal (); Cglib $ emptyargs = new Object [0]; Класс var0 = class.forname ("com.sl.aop.orderserviceimpl $$ Enhancerbycglib $$ 17779aa4"); Класс var1; Method [] var10000 = Refertutils.findmethods (new String [] {"equals", "(ljava/lang/object;) z", "tostring", "() ljava/lang/string;", "hashcode", "() i", "clone", "() ljava/lang/object; Class.forname ("java.lang.object")). GetDeclaredMethods ()); Cglib $ равна $ 1 $ method = var10000 [0]; Cglib $ равна $ 1 $ proxy = methodproxy.create (var1, var0, "(ljava/lang/object;) z", "equals", "cglib $ evall $ 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 = Refertutils.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 (это, cglib $ createorder $ 0 $ method, cglib $ emptyargs, cglib $ createorder $ 0 $ proxy); } else {super.createOrder (); / } 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 (это, cglib $ evall $ 1 $ Метод, новый объект [] {var1}, cglib $ evall $ 1 $ proxy); return var2 == null? false: ((boolean) var2) .booleanValue (); } else {return super.equals (var1); }} окончательная строка 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 (это, cglib $ toString $ 2 $ Метод, 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 (это, cglib $ hashcode $ 3 $ Метод, cglib $ emptyargs, cglib $ hashcode $ 3 $ proxy); вернуть var1 == null? 0: ((номер) var1) .intvalue (); } else {return super.hashcode (); / } защищенный конечный объект Clone () бросает 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 (это, cglib $ clone $ 4 $ Метод, 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; } перерыв; case -508378822: if (var10000.equals ("clone () ljava/lang/object;")) {return cglib $ clone $ 4 $ proxy; } перерыв; случай 1826985398: if (var10000.equals ("equals (ljava/lang/object;) z")) {return cglib $ evall $ 1 $ proxy; } перерыв; Case 1913648695: if (var10000.equals ("toString () ljava/lang/string;"))) {return cglib $ toString $ 2 $ прокси; } перерыв; 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 $ think_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 = новый orderserviceimpl $$ enhancerbycglib $$ 17779aa4 (); Cglib $ set_thread_callbacks ((callback []) null); вернуть var10000; } public Object newInstance (обратный вызов var1) {cglib $ set_thread_callbacks (новый обратный вызов [] {var1}); Orderserviceimpl $$ enhancerbycglib $$ 17779aa4 var10000 = новый orderserviceimpl $$ enhancerbycglib $$ 17779aa4 (); Cglib $ set_thread_callbacks ((callback []) null); вернуть var10000; } public Object newInstance (class [] var1, object [] var2, callback [] var3) {cglib $ set_thread_callbacks (var3); Orderserviceimpl $$ enhancerbycglib $$ 17779aa4 var10000 = новый orderserviceimpl $$ enhancerbycglib $$ 17779aa4; Switch (var1.length) {case 0: var10000. <int> (); Cglib $ set_thread_callbacks ((callback []) null); вернуть var10000; по умолчанию: бросить новое allogalargumentException («конструктор не найден»); }} public обратный вызов getCallback (int var1) {cglib $ bind_callbacks (this); MethodInterceptor var10000; Switch (var1) {case 0: var10000 = this.cglib $ callback_0; перерыв; по умолчанию: var10000 = null; } return var10000; } public void setCallback (int var1, callback var2) {switch (var1) {case 0: this.cglib $ callback_0 = (methodinterceptor) var2; по умолчанию:}} public Callback [] getCallbacks () {cglib $ bind_callbacks (this); вернуть новый обратный вызов [] {this.cglib $ callback_0}; } public void setCallbacks (callback [] var1) {this.cglib $ callback_0 = (methodInterceptor) var1 [0]; } static {cglib $ statichook1 (); }}В приведенном выше коде вы можете видеть, что класс Proxy Class orderserviceimpl $$ Enhancerbycglib $$ 17779AA4 наследует целевой класс orderserviceimpl и реализует фабрику интерфейса. В классе по доверенности генерируются два метода Cglib $ Createorder $ 0 и Createorder:
Метод CGLIB $ CREATERORD $ 0 напрямую вызывает supper.createOrder целевого класса. CREATEORORD
Метод Createorder сначала подсчитывает, реализован ли обратный вызов интерфейса MethodInterceptor. Если он существует, вызывается метод интерфейса интерфейса MethodInterceptor. Согласно предыдущей реализации, реализован вызов целевого метода. Object o1 = arg3.invokeSuper(arg0, arg2) реализован. Allokesuper на самом деле является методом CGLIB$createOrder$0() класса прокси, который называется непосредственно, и наконец -то вызван целевой класс Createorder.
Сравнение двух агентов
JDK Dynamic Proxy:
Класс прокси и класс делегатов реализует один и тот же интерфейс. В основном он реализует vlocationhandler через класс прокси и переписывает метод Anloke для выполнения динамического прокси. Метод будет улучшен в методе Invoke. Преимущества метода: не требуется жесткий интерфейс, а скорость повторного использования кода высока. Недостатки: только класс делегатов, который может быть реализован интерфейсом
CGLIB Dynamic Proxy:
Класс прокси принимает класс делегатов в качестве родительского класса и создает два метода для нефинальных методов делегата в нем. Один из них - тот же метод, что и сигнатура метода делегата, которая будет вызовать метод делегата через Super в методе; Другой - это метод, уникальный для прокси -класса. В методе прокси он определит, существует ли объект, который реализует интерфейс MethodInterceptor. Если он будет существует, метод перехвата будет вызван для прокси -диплома метода делегата. Преимущества: он может улучшить работу класса или интерфейса во время выполнения, а класс делегатов не нуждается в реализации интерфейса. Недостатки: он не может прокси и окончательный класс и окончательный метод.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.