Эта статья о сложной проблеме в Java. Используя библиотеку Java Core для реализации простых методов AOP и анализа и сравнения кода экземпляра. Ниже приведено все содержание:
Spring - очень популярная структура с открытым исходным кодом, а AOP (программирование секции) - одна из самых важных концепций пружины. Чтобы лучше понять и выучить идеи AOP, использование основной библиотеки для достижения ее за раз - хороший способ.
Во -первых, давайте представим концепцию AOP. AOP (ориентированное на аспект программирование), то есть тангенциально-ориентированное программирование. Так называемое тангенциальное программирование-это идея разработки кода с точки зрения области поперечного сечения. Традиционная идея ООП состоит в том, чтобы использовать наследование инкапсуляции и полиморфизм для построения вертикальных иерархических отношений, но это не подходит для определения горизонтальных отношений. AOP Idea обеспечивает хорошее дополнение к этому.
Например, код управления журналами часто горизонтально рассеивается во многих уровнях объектов, но он не имеет ничего общего с основными функциями соответствующих объектов. Существует также много аналогичных кодов, таких как проверка разрешений, вывод отладки, обработка транзакций и т. Д., Которые также одинаковы. Это не способствует повторному использованию кода и управлению.
В настоящее время технология AOP возникла. Он использует технологию «перекрестной» для глубокого проникновения в объект инкапсуляции, инкапсуляет общее поведение, которое влияет на множественные классы в многократный модуль, и назовите его «аспект», то есть нарезание. Так называемый «раздел» просто инкапсулируется логикой или обязанностями, которые не связаны с бизнесом, но называются совместно бизнес-модулем, что удобно для снижения дубликатного кода системы, уменьшения связи между модулями и способствуя последующей работой и обслуживаемости.
Так как же реализуется AOP?
Ответ - динамичный прокси (будет подробно рассказывать о прокси -сервере, поэтому я не буду вдаваться в подробности здесь). Существует два способа реализации динамического прокси, один из которых является динамическим прокси JDK, а другой - динамический прокси CGLIB.
Затем используйте два метода, чтобы сделать простой каштан.
Давайте сначала спроектируем сценарий, предположим, что у нас есть вычислительный интерфейс icalculator и калькулятор класса калькулятора, который реализует этот интерфейс.
Публичный интерфейс iCalculator {// Дополнение операции public int add (int a, int b); // вычитание общественности вычтите (int a, int b); // Несколько публичных int умножьте (int a, int b); // Dividation public int define (int a, int b);} открытый класс CalculatorImpl реализует iCalculator {@Override public int add (int a, int b) {return a + b; } @Override public int вычтите (int a, int b) {return a - b; } @Override public int multiply (int a, int b) {return a * b; } @Override public int define (int a, int b) {return a / b; }}Как записать общее количество раз, когда метод калькулятора используется без изменения внутреннего кода исходного класса калькулятора?
С динамическим прокси на самом деле это очень просто. Сначала создайте класс и реализуйте интерфейс InvocationHandler, переопределите метод Invoke.
Общедоступный класс TestHandler реализует InvocationHandler {Private Object TargetObject; Частный интенсивный раз; // Привязан объект делегата и вернуть Proxy Class Public Object Bind (Object TargetObject) {this.TargetObject = targetObject; return proxy.newProxyInstance (targetObject.getClass (). getClassLoader (), targetObject.getClass (). getInterfaces (), это); } @Override public Object invoke (объект прокси, метод метода, Object [] args) бросает Throwable {// делать что -то до (); Object result = method.invoke (targetObject, args); после(); результат возврата; } private void до () {System.out.println («Мы можем что -то сделать, прежде чем вычислять.»); } private void After () {usetimes ++; System.out.println («Используется:»+usetimes+«время»); }}Хотя кажется, что есть слишком много кода, основным методом является метод вызова. Объект result = method.invoke (targetObject, args); Это эквивалентно продолжению использования исходных параметров для выполнения исходного метода. До и после здесь представлены настраиваемые функции, которые могут делать некоторые вещи, которые мы хотим сделать до и после выполнения объектного кода, например, количество использования здесь.
В методе привязки целевой прокси -объект передается и возвращается экземпляр класса прокси. Далее, давайте посмотрим, как использовать:
public class testproxy {public static void main (string [] args) {testhandler proxy = new TestHandler (); Icalculator Расчет = (iCalculator) proxy.bind (new CalculatorImpl ()); int result = calculate.add (1,2); System.out.println («Результат:»+Результат); result = courtulate.subtract (3,2); System.out.println («Результат:»+Результат); Result = Calculater.Multiply (4,6); System.out.println («Результат:»+Результат); Result = Calculater.Devide (6,2); System.out.println («Результат:»+Результат); }}Сначала мы определяем тест -руку, а затем получаем экземпляр прокси по методу привязки, а затем мы можем использовать этот экземпляр напрямую. Результаты работы следующие:
Мы можем что -то сделать, прежде чем рассчитать. Используется: 1 Результат: 3 Мы можем что -то сделать, прежде чем вычислять. Используется: 2 Результат: 1 мы можем что -то сделать, прежде чем вычислять. Используется: 3 Результат: 24 Мы можем что -то сделать, прежде чем вычислять. Используется: 4 Результат: 3
Таким образом, мы реализуем расширение кода без изменения внутреннего кода CalculatorImpl.
Затем используйте CGLIB, чтобы реализовать его один раз.
Сначала создайте класс для реализации интерфейса MethodInterceptor и переопределить метод перехвата. Другие коды аналогичны использованию прокси JDK, но процесс получения прокси -объектов отличается.
открытый класс cglibproxy реализует Methodinterceptor {private int uset -times; Цель частного объекта; public Object getInstance (объект цели) {this.Target = target; Enhancer Enhancer = новый Enhancer (); Enhancer.setSuperClass (this.Target.getClass ()); Enhancer.SetCallback (это); return Enhancer.create (); } @Override public Object Intercept (Object O, метод метода, объект [] объекты, MethodProxy MethodProxy) бросает Throwable {до (); Object result = methodProxy.invokesuper (o, объекты); после(); результат возврата; } private void до () {System.out.println («Мы можем что -то сделать, прежде чем вычислять.»); } private void After () {usetimes ++; System.out.println («Используется:»+usetimes+«время»); }}Проверьте это:
открытый класс testcglibproxy {public static void main (string [] args) {cglibproxy cglibproxy = new cglibproxy (); Icalculator Расчет = (iCalculator) cglibproxy.getInstance (new CalculatorImpl ()); int result = calculate.add (1,2); System.out.println («Результат:»+Результат); result = courtulate.subtract (3,2); System.out.println («Результат:»+Результат); result = countulate.multiply (4,6); System.out.println («Результат:»+Результат); result = Countulate.Devide (6,2); System.out.println («Результат:»+Результат); }}Результаты работы следующие:
Мы можем что -то сделать, прежде чем рассчитать. Используется: 1 Результат: 3 Мы можем что -то сделать, прежде чем вычислять. Используется: 2 Результат: 1 мы можем что -то сделать, прежде чем вычислять. Используется: 3 Результат: 24 Мы можем что -то сделать, прежде чем вычислять. Используется: 4 Результат: 3
Теперь мы получаем тот же результат. (Требуются два пакета, Cglib-2.2.2.jar asm-3.3.jar)
Оба метода имеют свои сильные стороны. JDK Proxy должен настроить интерфейс перед реализацией прокси. Это его недостаток и его преимущество. Недостаток заключается в том, что это будет немного более хлопотно, и он не может прокси ранее инкапсулирован и не реализует интерфейс. Метод прокси -сервера CGLIB не требует использования интерфейсов. Но именно из -за этого прокси JDK перехватывает только методы, которые перезаписывают интерфейсы в классе, в то время как Cglib перехватывает все вызовы методов класса. Оба имеют свои плюсы и минусы, поэтому необходимо проанализировать конкретные обстоятельства. Весной используются два прокси -режима.