Статьи

JSR-299 CDI Декораторы для фасоли

 Этот блог о моих новых усилиях по созданию модулей Spring-CDI. Цель состоит в том, чтобы сделать полезные шаблоны CDI, такие как декораторы или перехватчики, доступными для приложения Spring. Я действительно считаю, что явная реализация шаблона в CDI очень полезна. Это делает очевидным и простым использование шаблонов для не очень опытных разработчиков. Поэтому я решил изучить, как сделать эти шаблоны и соответствующие аннотации CDI доступными для управляемых компонентов Spring. Вот текущее состояние моей работы. Если вам интересно, и у вас осталось немного времени, посмотрите или попробуйте мою раннюю версию модуля декоратора Spring-CDI. Установка прямо вперед. Вы найдете все, что вам нужно ниже.

Обратите внимание: цель моего блога — поделиться идеями и обсудить их. Если вы используете это в своих приложениях, вы действуете на свой страх и риск.

Особенности
реализации шаблона декоратора JSR-299

Модуль декоратора предоставляет следующие функции:

— Использование JSR-299 @Decorator и @Delegate в управляемых bean-компонентах Spring

— Поддержка цепочек нескольких декораторов для одного и того же целевого bean-компонента делегата

— Позволяют квалифицировать декораторы для декорации нескольких реализаций одного и того же интерфейса с различными декораторами

— поддержка bean-

объектов bean-scoped,
разрешение декораторов- scoped — интеграция с Spring AOP, как с динамическими JDK-прокси, так и с CGLIB-прокси
— разрешить определение пользовательских декораторов и аннотаций делегатов

Download Link

Модуль декоратора Spring-CDI — это обычное расширение IoC-контейнера Spring, поставляемое в виде архива JAR. Вы можете скачать модуль JAR и поместить его в путь к классу вашего приложения Spring.

Скомпилированный модуль декоратора Spring-CDI JAR:
скачать здесь

Источники:
скачать здесь

API-Doc:
посмотреть здесь

Все размещено
в репозитории git на Github.com .

зависимости

<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
<version>${spring.version}</version>
</dependency>
 
<dependency>
<groupid>org.springframework</groupid>
<artifactid>org.springframework.aop</artifactid>
<version>${spring.version}</version>
</dependency>
 
<dependency>
<groupid>javax.enterprise</groupid>
<artifactid>cdi-api</artifactid>
<version>1.0</version>
</dependency>
 
<dependency>
<groupid>cglib</groupid>
<artifactid>cglib</artifactid>
<version>2.2.2</version>
</dependency>

Конфигурация

Если JAR-модуль Spring-CDI-декоратора и его зависимости находятся на вашем пути к классам, все, что вам нужно сделать, это:

(1) зарегистрировать
DecoratorAwareBeanFactoryPostProcessor в контексте вашего приложения

(2) определить include-фильтр для включения javax.decorator.Decorator в качестве компонента аннотация в вашем контексте: тег компонентного сканирования

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
default-autowire="byName">

<context:component-scan base-package="com.mycompany.springapp.springcdi" scoped-proxy="targetClass">
<context:include-filter type="annotation" expression="javax.decorator.Decorator" />
</context:component-scan>

<bean class="com.schlimm.springcdi.decorator.DecoratorAwareBeanFactoryPostProcessor" />

</beans>

Вариант использования

В следующих фрагментах кода показано, как можно использовать шаблоны декоратора, которые вы настроили в приложении Spring, как описано выше. Для более сложных сценариев смотрите мои примеры модульных тестов.

Предположим, у вас есть бизнес-интерфейс под названием: MyService

package com.mycompany.springapp.springcdi;
 
public interface MyService {
 
String sayHello();
 
}

Это ваша реализация сервиса.

	
package com.mycompany.springapp.springcdi;
 
import org.springframework.stereotype.Component;
 
@Component
public class MyServiceImpl implements MyService {
 
public String sayHello() {
return "Hello";
}
 
}

Вы хотите сделать некоторые транзакции и меры безопасности, но вы не хотите испортить бизнес-код с ним.

В целях безопасности вы должны написать декоратор, который указывает на бизнес-сервис MyService.

package com.mycompany.springapp.springcdi;
 
import javax.decorator.Decorator;
import javax.decorator.Delegate;
 
@Decorator
public class MyServiceSecurityDecorator implements MyService {
 
@Delegate
private MyService delegate;
 
public String sayHello() {
// do some security stuff
return delegate.sayHello();
}
 
}

Для разделения сквозных задач вы пишете другой декоратор для обработки транзакций, который указывает на бизнес-службу MyService.

package com.mycompany.springapp.springcdi;
 
import javax.decorator.Decorator;
import javax.decorator.Delegate;
 
@Decorator
public class MyServiceTransactionDecorator implements MyService{
 
@Delegate
private MyService delegate;
 
public String sayHello() {
// do some transaction stuff
return delegate.sayHello();
}
 
}

Тогда вы можете просто использовать стандартную аннотацию Spring @Autowired, чтобы это работало. Внедренный компонент будет украшен вашим новым декоратором безопасности и транзакций.

package com.mycompany.springapp.springcdi;
 
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
@ContextConfiguration("/test-decorator-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class DecoratorTestCase {
 
// This injected bean will be a decorated MyServiceImpl
@Autowired
private MyService service;
 
@Test
public void testHelloWorld() {
 
Assert.assertTrue(service.sayHello().equals("Hello"));
 
}
}

Как это работает

Ядром является
DecoratorAwareBeanFactoryPostProcessor, который сканирует определения зарегистрированных bean-компонентов для существующих декораторов. Он собирает метаданные и сохраняет эти данные в
DecoratorMetaDataBean .
DecoratorAwareBeanPostProcessor использует мета — данные , чтобы телеграфировать декораторов в цепочку и создает прокси CGLIB что метод перехватывает вызовы к целевой делегат боба. Он перенаправляет эти вызовы в цепочку декораторов.
DecoratorAutowireCandidateResolver применяет правила автоматического связывания , специфичные для данного шаблона КДИ декоратора. Для этого также используются метаданные.

Два режима

DecoratorAwareBeanFactoryPostProcessor принимает два режима выполнения. Режим «процессор» (по умолчанию) использует
DecoratorAwareBeanPostProcessor и
DecoratorChainingStrategy для связывания цепочки декоратора. Режим распознавателя использует
DecoratorAwareAutowireCandidateResolver для реализации пользовательской логики проводки, основанной на сложных правилах проводки, реализованных в
ResolverCDIAutowiringRules . Режим «распознавателя» был просто еще одним вариантом, как можно реализовать такую ​​сложную логику. Я попробовал два разных варианта и оба работают. Однако альтернатива «процессор» реализует более простую логику. Поэтому это мой предпочтительный режим на данный момент.

Мета-модель декоратора

DecoratorAwareBeanFactoryPostProcessor сканирует определения компонентов и сохраняет метаданные о декораторах и делегатах в контексте приложения. Это бины модели в их иерархическом порядке доступа:

DecoratorMetaDataBean.java : точка входа верхнего уровня в метаданные. Зарегистрировано и доступно в контексте приложения.

QualifiedDecoratorChain.java : Цепочка декораторов для одного и того же целевого компонента делегата.

DecoratorInfo.java : Класс-оболочка для определения bean-компонента decorator.

DelegateField.java : Содержит поле делегата реализации декоратора.

Стратегии

Модуль декоратора Spring-CDI легко внедряется пользователями благодаря использованию шаблона стратегии во многих местах. Это стратегии, которые позволяют пользователям изменять логику обработки при необходимости:

DecoratorChainingStrategy.java : связывает декораторы для конкретного целевого bean-компонента делегата.

DecoratorOrderingStrategy.java : Упорядочивает декораторы для определенного целевого bean-компонента делегата.

DecoratorResolutionStrategy.java : Сканирует фабрику bean-компонентов на наличие доступных bean-компонентов decorator.

DelegateResolutionStrategy.java : Ищет bean-компонент делегата для определенного bean-компонента декоратора.

Правила электромонтажа декоратора

Режим «процессор» и режим «решатель» используют собственный AutowireCandidateResolver, примененный к текущей фабрике бинов. Класс называется
DecoratorAwareAutowireCandidateResolver и применяется к фабрике бинов в DecoratorAwareBeanFactoryPostProcessor. Пользовательский распознаватель работает с различными наборами правил. В режиме «процессор» он работает с очень простым набором правил, который называется
BeanPostProcessorCDIAutowiringRules . В режиме «распознавателя» он использует
ResolverCDIAutowiringRules, который намного сложнее. Если этих наборов правил недостаточно для вашей логики автоматического подключения, можно легко применить дополнительные наборы правил, реализовав собственный
SpringCDIPlugin и добавив его в DecoratorAwareAutowireCandidateResolver.

Система плагинов

Spring-CDI Модуль декоратора Spring-CDI содержит два инфраструктурных интерфейса, которые обеспечивают модульный подход проекта Spring-CDI:
SpringCDIPlugin и
SpringCDIInfrastructure . Когда я внедряю дополнительные модули — например, модуль перехватчика — пользователи могут решать, какие модули использовать и импортировать в свои проекты. Не обязательно добавлять все функции Spring-CDI, если нужны только декораторы.

От http://niklasschlimm.blogspot.com/2011/08/jsr-299-cdi-decorators-for-spring-beans.html