Статьи

Перехватчики Java EE

история

Я думаю, что важно взглянуть на эволюцию Interceptors в Java EE из-за того простого факта, что он начинался как элемент, специфичный для EJB, а позже превратился в отдельную спецификацию, которая теперь открыта для расширения другими спецификациями Java EE.

Версия 1.0

Перехватчики были впервые представлены в  EJB 3.0  (часть  Java EE 5 ). У перехватчиков не было специальной спецификации, но они были версии 1.0 и купили базовые функции, связанные с AOP, для управляемых компонентов (POJO) с помощью простых аннотаций.

  • @AroundInvoke  — комментировать методы, содержащие логику перехвата для методов целевого класса
  • @Intercerptors  — связать классы-перехватчики с их целевыми классами / методами
  • Возможность настройки перехватчиков для всего модуля (EJB JAR) через дескриптор развертывания
  • @ExcludeDefaultInterceptors  — чтобы отключить перехватчики по умолчанию, определенные в дескрипторе развертывания
  • @ExcludeClassInterceptors  — отключить глобально определенный перехватчик (на уровне класса) для определенного метода / конструктора класса

Перехватчики 1.1

Вместе с  Java EE 6  с  EJB 3.1  — перехватчики 1.1 все еще были включены в спецификацию EJB

  • @InterceptorBinding  — безопасный для типа способ указания перехватчиков класса или метода. Обратите внимание, что эта аннотация была использована  CDI 1.0  (еще одна спецификация, представленная в Java EE 6), и  ее подробности представлены в спецификации документа CDI 1.0, а не в EJB 3.1  (момент лампочки… по крайней мере, для меня)
  • @Interceptor  — Используется для явного объявления класса, содержащего логику перехвата в конкретном методе (аннотированном @AroundInvoke и т. Д.), В качестве перехватчика вместе с соответствующей привязкой перехватчика. Это также упоминалось только в документации CDI 1.0.
  • @AroundTimeout  — используется для перехвата тайм-аутов таймеров EJB вместе со способом получения экземпляра перехватываемого таймера (через javax.interceptor.InvocationContext.getTimer () )

Перехватчики 1.2

Перехватчики были разделены на отдельные спецификации в  Java EE 7  и, таким образом,  появились Interceptors 1.2.

  • Interceptors 1.2 был техническим выпуском поверх 1.1, и, следовательно, номер JSR оставался таким же, как EJB 3.1 ( JSR 318 )
  • Interceptor.Priority  (статический класс) — для предоставления возможности определить порядок (приоритет), в котором должны вызываться перехватчики.
  • @AroundConstruct  — используется для перехвата конструирования целевого класса, то есть вызова логики до вызова конструктора целевого класса

Важно помнить, что Interceptors применимы к управляемым bean-компонентам в целом. Сами управляемые компоненты являются простыми объектами POJO, которые контейнер предоставляет привилегированные базовые сервисы — перехватчики являются одним из них наряду с обратными вызовами жизненного цикла, внедрением ресурсов.

Память Помощь

Полезно думать о Interceptors как о компонентах, которые могут вставляться в bean-компоненты на протяжении всего их жизненного цикла.

  • прежде чем они даже построены —  @AroundConstruct
  • после того, как они построены —  @PostConstruct
  • в течение их жизни (вызов метода) —  @AroundInvoke
  • до уничтожения —  @PreDestroy
  • время ожидания EJB —  @AroundTimeout

Blog_JavaEE_Interceptors

Давайте рассмотрим некоторые черты перехватчиков более подробно и попробуем ответить на такие вопросы, как

  • где они применяются и что они перехватывают?
  • как привязать перехватчики к цели (классу), которую они должны перехватить?

Типы перехватчиков (на основе перехваченного компонента)

Метод Перехватчики

  • Достигается  @AroundInvoke
    public class MethodInterceptor{
    	@AroundInvoke
    	public Object interceptorMethod(InvocationContext ictx) throws Exception{
    		//logic goes here
    	}
    }
     
    @Stateless
    public class AnEJB{
    	@Interceptors(MethodInterceptor.class)
    	public void bizMethod(){
    		//any calls to this method will be intercepted by MethodInterceptor.interceptorMethod()
    	}
    }
  • Метод, содержащий логику, может быть частью отдельного класса, а также самого целевого класса (класса, который должен быть перехвачен).

Перехватчики жизненного цикла

  • Украсьте метод с помощью  @AroundConstruct  , чтобы перехватить вызов конструктора для класса
    public class ConstructorInterceptor{
    	@AroundConstruct
    	public Object interceptorMethod(InvocationContext ictx) throws Exception{
    		//logic goes here
    	}
    }
     
    public class APOJO{
    	@Interceptors(ConstructorInterceptor.class)
    	public APOJO(){
    		//any calls to this constructor will be intercepted by ConstructorInterceptor.interceptorMethod()
    	}
    }
  • Метод, аннотированный @AroundConstruct, не может быть частью перехваченного класса. Он должен быть определен с использованием отдельного класса Interceptor
  • Use the @PostConstruct annotation on a method in order to intercept a call back method on a managed bean. Just to clarify again – the Interceptor spec does not define a new annotation as such. One needs to reuse the @PostConstruct (part of theCommon Annotations spec) on the interceptor method.
    public class PostConstructInterceptor{
    	@PostConstruct
    	public void interceptorMethod(InvocationContext ictx) throws Exception{
    		//logic goes here
    	}
    }
     
    @Interceptors(PostConstructInterceptor.class)
    public class APOJO{
    	@PostConstruct
    	public void bizMethod(){
    		//any calls to this method will be intercepted by PostConstructInterceptor.interceptorMethod()
    	}
    }
  • The @PreDestroy (another call back annotation defined in Common Annotations spec) annotation is used in a similar fashion

Time-out Interceptors

  • As mentioned above – @AroundTimeout used to intercept time outs of EJB timers along with a way to obtain an instance of the Timer being intercepted (viajavax.interceptor.InvocationContext.getTimer())

Applying/Binding Interceptors

Using @Interceptors

  • As shown in above examples – just use the @Interceptors annotation to specify the interceptor classes
  • @Interceptors can be applied on a class level (automatically applicable to all the methods of a class), to a particular method or multiple methods and constructor in case of a constructor specific interceptor using @AroundConstruct

Using @IntercerptorBinding

  • Interceptor Bindings (explained above) – Use @IntercerptorBinding annotation to define a binding annotation which is further used on the interceptor class as well as the target class (whose method, constructor etc needs to be intercepted)
    @InterceptorBinding 
    @Target({TYPE, METHOD, CONSTRUCTOR}) 
    @Retention(RUNTIME) 
    public @interface @Auditable {
    }
     
    @Auditable 
    @Interceptor
    public class AuditInterceptor {
    	@AroundInvoke
    	public Object audit(InvocationContext ictx) throws Exception{
    		//logic goes here
    	}
    }
     
    @Stateless
    @Auditable
    public class AnEJB{
    	public void bizMethod(){
    		//any calls to this method will be intercepted by AuditInterceptor.audit()
    	}
    }
Deployment Descriptor

One can also use deployment descriptors to bind interceptors and target classes either in an explicit fashion as well as in override mode to annotations.

This was a rather quick overview of Java EE interceptors. Hopefully the right trigger for you to dig deeper ?

Cheers !