представлять
Как мы все знаем, AOP (программы, ориентированное на раздел), является одной из особенностей пружинных рамок. AOP обеспечивает чрезвычайно высокую масштабируемость, устанавливая проблемы с перекрестными резаниями. Итак, как AOP работает весной? Когда вы можете использовать только основную Java, но нуждаются в технологии AOP, ответ на этот вопрос становится чрезвычайно критическим. Мало того, в интервью для продвинутых технических должностей такие вопросы часто появляются в качестве тестовых вопросов. Послушайте, мой друг недавно посетил интервью, и мне задали такой сложный вопрос - как реализовать AOP без использования весенних и связанных библиотеков, и только основной Java. Поэтому я предоставлю наброски в этой статье, чтобы помочь вам понять, как реализовать AOP с использованием Core Java (конечно, этот AOP имеет определенные функциональные ограничения). Обратите внимание, что эта статья не является сравнительным исследованием Spring AOP и Java AOP, а учебным пособием по реализации AOP с помощью неотъемлемых моделей проектирования в Core Java.
Я полагаю, что читатели уже знают, что такое AOP и как его использовать в рамках Spring, поэтому эта статья фокусируется только на том, как реализовать AOP без использования Spring. Прежде всего, мы должны знать, что Spring использует две технологии: JDK Proxy и Cglib для реализации AOP. JDK Dynamic Proxy обеспечивает гибкий способ подключить метод и выполнить указанные операции, но при выполнении операций должно быть ограничение: связанный интерфейс и класс реализации интерфейса должны быть сначала предоставлены. Практика для создания истинных знаний, давайте поймем это предложение через дело! В настоящее время существует калькуляторная программа для выполнения некоторых математических операций. Давайте рассмотрим функцию разделения. Вопрос в настоящее время: если основная структура уже имеет код для реализации подразделения, можем ли мы захватить его и выполнить дополнительную проверку при выполнении кода? Ответ - да, и я докажу это с помощью фрагмента кода, указанного ниже. Во -первых, давайте посмотрим на код базового интерфейса:
Калькулятор общественного интерфейса {public int Расчет (int a, int b);}Код этого класса реализации интерфейса выглядит следующим образом:
открытый класс CalculatorImpl реализует калькулятор {@Override public int Расчет (int a, int b) {return a/b; }}Предполагая, что мы не можем восстановить приведенный выше код или внести какие -либо изменения в основную библиотеку, как мы можем идеально реализовать функцию проверки? Почему бы не попробовать функцию динамического прокси -сервера JDK.
Общедоступный класс Somehandler реализует InvocationHandler {// код пропущен для простоты… .. @Override Public Object Invoke (Proxy Object, метод метода, объект [] params) бросает Throwable {// Ваша сложная валидация бизнеса и логический объект result = method.invoke (targetObject, params); результат возврата; }}Давайте посмотрим, как функция проверки, реализованная JDK Dynamic Proxy, работает через тестовый класс.
public static void main (string [] args) {calculatorImpl calcimpl = new CalculatorImpl (); Калькулятор проксирован = (калькулятор) proxyfactory.getProxy (calculator.class, calcimpl, new somehandler (calcimpl)); int result = proxied.calculate (20, 10); System.out.println ("Окончательный результат :::" + result); }Из результатов мы видим, что, просто внедрив мощный интерфейс InvocationHandler, мы можем получить реализацию зацепления. Согласно документации JDK, интерфейс InvocationHandler использует экземпляр прокси для обработки вызова метода.
Теперь мы знаем, что метод Invoke () vocationHandler может помочь нам решить проблему. Итак, давайте решим новую проблему - как мы можем выполнять операции до и после выполнения метода? Чтобы выразить это более конкретно, можем ли мы подключить метод, добавив несколько AOP (до, после, вокруг) (Примечание переводчика: исходный текст добавляет несколько AOP, но я думаю, что обработчик действует как аспект)? Ответ тоже да. Следуйте приведенным ниже шагам, чтобы создать оптимизированный шаблон кода, чтобы удовлетворить это требование:
Два способа реализации AOP:
1. Динамическая реализация прокси, предоставленную JDK
интерфейс
публичный интерфейс пользовательский завод {void getUser (); void AddUser (); void UpdateUser (); void deleteUser (); } Оригинальный класс реализации
открытый класс UserBeanImpl реализует userbean {private String user = null; public userBeanImpl () {} public userBeanImpl (String user) {this.user = user; } public String getUsername () {return user; } public void getUser () {System.out.println ("Это метод getUser ()!"); } public void setUser (String user) {this.user = user; System.out.println («Это метод setuser ()!»); } public void AddUser () {System.out.println ("Это метод adduser ()!"); } public void UpdateUser () {System.out.println ("Это метод обновления () ()!"); } public void deleteUser () {System.out.println ("Это метод deleteUser ()!"); }} Агент класс
импортировать java.lang.reflect.invocationHandler; импортировать java.lang.reflect.method; Импорт java.lang.reflect.proxy; Импорт com.cignacmc.finance.bean.userbeanimpl; открытый класс пользовательский, реализует upocationHandler {private Object TargetObject; public userBeanProxy (Object TargetObject) {this.TargetObject = targetObject; } public Object Invoke (Proxy Object, метод метода, объект [] args) бросает throwable {userBeanImpl userBean = (userBeanImpl) TargetObject; String username = userbean.getusername (); Объект результат = null; // разрешение суждения if (username! = Null &&! } return Result; }}
Тестовый класс
Импорт java.lang.reflect.proxy; Импорт com.cignacmc.finance.bean.userbean; Импорт com.cignacmc.finance.bean.userbeanimpl; Импорт com.cignacmc.finance.proxy.userbeanproxy; открытый класс ProxeExe {public static void main (string [] args) {System.out.println ("Доказано ........."); UserBeanImpl targetObject = new UserBeanImpl ("Bob Liang"); Userbeanproxy proxy = new UserbeanProxy (TargetObject); // генерировать объект Proxy Userbean Object = (userbean) proxy.newProxyInstance (targetObject.getClass (). GetClassLoader (), targetObject.getClass (). GetInterfaces (), proxy); Object.Adduser (); System.out.println («Нет доказано ............»); targetObject = new UserBeanImpl (); proxy = new UserbeanProxy (TargetObject); // генерировать объект Proxy Object = (userBean) proxy.newProxyInstance (targetObject.getClass (). GetClassLoader (), targetObject.getClass (). GetInterfaces (), proxy); Object.Adduser (); }}
Выход:
Доказано ............ Это метод Adduser ()! Нет доказано ..........
Из приведенного выше примера вызываемый метод adduser () может быть успешно перехвачен и обработан соответственно.
2. Создайте класс прокси через CGLIB
Преимущество заключается в том, что наш целевой объект не требует реализации примитивного класса интерфейса.
открытый класс ClientBean {Private String name = null; public ClientBean () {} public ClientBean (String name) {this.name = name; } public void addClient () {System.out.println ("Это метод addClient ()!"); } public void deleteClient () {System.out.println ("Это метод deleteclient ()!"); } public void getClient () {System.out.println ("Это метод getClient ()!"); } public void getClient () {System.out.println ("Это метод getClient ())!"); } public void updateClient () {System.out.println ("Это метод updateclient ()!"); } public String getClientName () {return name; } public void setClientName (String name) {this.name = name; }} Агент класс
импортировать java.lang.reflect.method; Импорт com.cignacmc.finance.bean.clientbean; Импорт net.sf.cglib.proxy.enhancer; Импорт net.sf.cglib.proxy.methodinterceptor; Импорт net.sf.cglib.proxy.methodinterceptor; Импорт net.sf.cglib.proxy.methodproxy; открытый класс cglibproxy реализует MethodInterceptor {private Object TargetObject; public Object createProxyObject (объект TargetObject) {this.TargetObject = targetObject; Enhancer Enhancer = новый Enhancer (); Enhancer.setSuperClass (this.TargetObject.getClass ()); Enhancer.SetCallback (это); return Enhancer.create (); } public Object Intercept (объект прокси, метод метода, объект [] args, methodproxy methodproxy) бросает Throwable {clientBean clientBean = (ClientBean) TargetObject; String username = clientBean.getClientName (); Объект результат = null; if (username! = null &&! "". } return Result; }} Тестовый класс
Импорт java.lang.reflect.proxy; Импорт com.cignacmc.finance.bean.clientbean; Импорт com.cignacmc.finance.bean.userbean; Импорт com.cignacmc.finance.bean.userbeanimpl; Импорт com.cignacmc.finance.proxy.cglibproxy; Импорт com.cignacmc.finance.proxy.userbeanproxy; public Class ProxeExe {public static void main (string [] args) {System.out.println ("........ прокси Cglib ............"); System.out.println ("доказано ..............."); Cglibproxy cproxy = new cglibproxy (); ClientBean ClientBean = (ClientBean) cProxy.CreateProxyObject (New ClientBean ("Bob Liang")); clientbean.addclient (); System.out.println ("Нет доказано ..............."); cProxy = new cglibproxy (); ClientBean = (ClientBean) cProxy.CreateProxyObject (new ClientBean ()); clientbean.addclient (); }}
Выход:
..... Cglib Proxy .................. доказано ............ Это метод addClient ()! Нет доказано ............