Статьи

Понимание динамического прокси: основы Spring AOP

Почему АОП:

Чтобы понять AOP (Аспектно-ориентированное программирование), мы должны понимать сквозные проблемы в разработке программного обеспечения. В каждом проекте есть некоторый объем кода, который повторяется в нескольких классах, в нескольких модулях. Например, ведение журнала, которое необходимо выполнить почти для всех классов и для всех модулей.

Этот вид кода снижает возможности его повторного использования, обслуживания и масштабируемости. Например, если вы хотите взять класс и повторно использовать его где-то еще, где регистрация не нужна, вы должны изменить этот класс. Точно так же, если проверка или регистрация изменяются, мы должны изменить почти каждый класс, где бы он ни использовался.

Класс должен сосредоточиться на своей основной функциональности, такие вещи, как ведение журнала, проверка, транзакция и т. Д. Не являются частью функциональности класса. Аспектно-ориентированное программирование — это парадигма, которая помогает нам устранить эти сквозные проблемы. Он предоставляет нам инструменты и методологию для отделения нашего сквозного кода от классов.

Шаблон прокси:

Мы можем создать прокси объекта, который позаботится о сквозном коде. Существует два вида шаблонов прокси:

  • Статический прокси:

    Где мы создаем прокси-объект для каждого класса. Это неосуществимо и практично

  • Динамический прокси:

    В этом прокси создаются динамически через отражение. Эта функциональность добавлена ​​из JDK 1.3. динамический прокси образует основной строительный блок Spring AOP

Здесь Class Example1 реализует интерфейс BasicFunc.

01
02
03
04
05
06
07
08
09
10
package com.somaniab.blog.ex;
 
public class Example1 implements Basicfunc{
 
 @Override
 public void method1() {
  System.out.println("executing method 1"); 
 }
 
}

Вот интерфейс Basicfunc

1
2
3
4
5
6
7
package com.somaniab.blog.ex;
 
public interface Basicfunc{
 
 public void method1();      
 
}

Теперь, если мы хотим вычислить время выполнения method1, мы должны написать этот код в самом методе или создать прокси-объект. Для создания прокси-объекта мы создаем обработчик Invocation:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.somaniab.blog.ex;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class MyInvocationHandler implements InvocationHandler{
 
 private Object target ;
 
        public MyInvocationHandler(Object target)
 {
  this.target = target;
 }
 
 public Object getTarget() {
  return target;
 }
 
 public void setTarget(Object target) {
  this.target = target;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] params)
   throws Throwable {
  long a = System.currentTimeMillis();
  Object result =method.invoke(target ,params);
  System.out.println("total time taken  "+
                         (System.currentTimeMillis()-a));
  return result;
 }
 
}

В этом обработчике вызовов мы вызываем фактический метод, а также вычисляем время, затраченное на выполнение. Теперь в основном классе мы создаем объект прокси с помощью класса Proxy.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.somaniab.blog.ex;
 
import java.lang.reflect.Proxy;
 
public class MainClass {
      public static void main(String[] args) {
 
       Example1 ex = new Example1();
 
       Basicfunc proxied =(Basicfunc)Proxy
                           .newProxyInstance(MainClass.class.getClassLoader(),
         ex.getClass().getInterfaces() ,new MyInvocationHandler(ex));
       proxied.method1();
 }
}

Для создания Proxy мы передаем загрузчик классов [в основном тот же загрузчик классов, что и исходный класс], интерфейсы и invocationHandler (передаем исходный целевой объект в обработчик вызова). Исходный класс должен реализовывать интерфейс, только те методы, которые объявлены в интерфейсе, проксируются, а затем мы приводим прокси к типу интерфейса.

Если вы получаете Exception, как это: java.lang.ClassCastException: $ Proxy0 не может быть приведен к com.somaniab.blog.ex.Example1 , это означает, что ваш целевой класс не реализует интерфейс.

В CGLib Proxy нет необходимости объявлять интерфейс. Итак, вот как мы убедились, что наш пример класса пишет код только для method1, и мы сохранили из него код вычисления времени выполнения. Это очень простой пример, но это основной Spring AOP. Другими интегрированными средами, отличными от Spring AOP, являются AspectJ и JBOSS AOP.

Ссылка: Понимание динамического прокси: основы Spring AOP от нашего партнера JCG Абхишека Сомани из блога Java, J2EE, Server .