public class LoggingProducer {
··@Produces
··public Logger produceLogger(InjectionPoint injectionPoint) {
····return Logger.getLogger(injectionPoint.getMember(). getDeclaringClass(). getName());
··}
}
Класс LoggingInterceptor в листинге 2.49 использует произведенный Logger для регистрации входа в методы и выхода из них. Поскольку запись в журнал может рассматриваться как сквозная функциональность, она отдельно реализуется в виде перехватчика (@AroundInvoke на logMethod). Класс LoggingInterceptor определяет связь с перехватчиком @Loggable (листинг 2.50) и может впоследствии применяться в любом компоненте (например, BookService в листинге 2.40).
@Interceptor
@Loggable
public class LoggingInterceptor {
··@Inject
··private Logger logger;
··@AroundInvoke
··public Object logMethod(InvocationContext ic) throws Exception {
····logger.entering(ic.getTarget(). getClass(). getName(),
ic.getMethod(). getName());
····try {
······return ic.proceed();
····} finally {
······logger.exiting(ic.getTarget(). getClass(). getName(),
ic.getMethod(). getName());
····}
··}
}
@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Loggable { }
Написание класса Main
Для запуска демонстрационного приложения нам необходим основной класс (назовем его Main), который приводит в действие контейнер CDI и вызывает метод BookService.createBook. CDI 1.1 не имеет стандартного API для начальной загрузки контейнера, поэтому код в листинге 2.51 специфичен для Weld. В первую очередь он инициализирует WeldContainer и возвращает полностью сконструированную и внедренную сущность BookService.class. Затем вызов метода createBook станет использовать все сервисы контейнера: IsbnGenerator и Logger будут внедрены в BookService с последующим созданием и отображением Book с номером ISBN.
public class Main {
··public static void main(String[] args) {
····Weld weld = new Weld();
····WeldContainer container = weld.initialize();
····BookService bookService =
container.instance(). select(BookService.class). get();
····Book book = bookService.createBook("H2G2", 12.5f, "Интересная книга
········································на тему высоких технологий");
····System.out.println(book);
····weld.shutdown();
··}
}
Код в листинге 2.51 специфичен для Weld, поэтому его нельзя портировать. Он не будет работать на других реализациях CDI, таких как OpenWebBeans (Apache) или CanDI (Caucho). Одна из целей будущего релиза CDI — стандартизировать API для начальной загрузки контейнера.
Приведение в действие CDI с beans.xml
Чтобы привести в действие CDI и позволить демонстрационному приложению заработать, нам требуется файл beans.xml в пути к классам приложения. Как следует из листинга 2.52, файл beans.xml совершенно пуст, но без него нельзя будет задействовать CDI, осуществить обнаружение компонентов либо внедрение.
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
·······xmlns: xsi="http://www.w3.org/2001/XMLSchema-instance"
·······xsi: schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
····························http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
·······version="1.1" bean-discovery-mode="all">
</beans>
Компиляция и выполнение с помощью Maven
Теперь необходимо скомпилировать все классы перед запуском класса Main и интеграционным тестом BookServiceIT. Файл pom.xml в листинге 2.53 объявляет все необходимые зависимости для компиляции кода (org.jboss.weld.se: weld-se содержит APICDI и реализацию Weld) и запуска теста (junit: junit). Указание версии 1.7 в maven-compiler-plugin означает, что вы хотите использовать Java SE 7 (<source>1.7</source>). Заметьте, что мы применяем exec-maven-plugin для того, чтобы иметь возможность выполнить класс Main с помощью фреймворка Maven.