java与java ee
Java EE 6允许我们通过CDI创建装饰器,作为其AOP功能的一部分。 如果我们想实现仍然与业务足够接近的跨领域关注点 ,则可以使用Java EE 6的此功能。
假设您有一项票务服务,可让您订购特定事件的票务。 TicketService处理注册等,但是我们要添加餐饮。 我们不认为这是门票订购逻辑的一部分,因此我们创建了一个装饰器。 装饰者将调用TicketService并添加门票数量。
界面:
public interface TicketService {Ticket orderTicket(String name);
}
接口的实现,创建票证并将其保留。
@Stateless
public class TicketServiceImpl implements TicketService {@PersistenceContextprivate EntityManager entityManager;@TransactionAttribute@Overridepublic Ticket orderTicket(String name) {Ticket ticket = new Ticket(name);entityManager.persist(ticket);return ticket;}
}
当我们不能使用装饰器时,我们可以创建相同接口的新实现。
@Decorator
public class TicketServiceDecorator implements TicketService {@Inject@Delegateprivate TicketService ticketService;@Injectprivate CateringService cateringService;@Overridepublic Ticket orderTicket(String name) {Ticket ticket = ticketService.orderTicket(name);cateringService.orderCatering(ticket);return ticket;}
}
请注意,我们在此处应用了2个CDI特定注释。 @Decorator将实现标记为装饰器。 装饰器应始终具有一个委托(我们要装饰的类),该委托带有@Delegate批注(在注入点处)标记。 还请注意我们使用接口而不是实现的事实。
就像其他示例一样 ,当您注入此接口时,将使用常规实现。
@Inject private TicketService ticketService;
不必使用限定符,我们只需要调整beans.xml即可将TicketServiceDecorator标记为“ Decorator”。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"><decorators><class>be.styledideas.blog.decorator.TicketServiceDecorator</class></decorators>
</beans>
作为更高级的用法,我们可以组合多个装饰器并选择我们希望它们执行的顺序。
如果您有用例,则可以像这样在beans.xml文件中轻松定义两个装饰器。
<decorators><class>be.styledideas.blog.decorator.HighDecorator</class><class>be.styledideas.blog.decorator.LowDecorator</class>
</decorators>
因此,当我们调用装饰类时,我们得到了高级装饰器入口,低装饰器入口,实际装饰器类,低装饰器出口,高装饰器出口。 因此,文件中的装饰器顺序确实很重要。
第二个功能比第一个功能更具吸引力,它揭示了Java EE6中Decorator功能的真正威力。 这是将其与CDI批注结合在一起的能力。 作为示例,我将使用社交媒体供稿处理器。
所以我创建了一个接口:
public interface SocialFeedProcessor {Feed process(String feed);
}
并提供了2种实现,twitter和google +
public class TwitterFeedProcessor implements SocialFeedProcessor{@Overridepublic Feed process(String feed) {System.out.println("processing this twitter feed");// processing logicsreturn new Feed(feed);}}
public class GooglePlusFeedProcessor implements SocialFeedProcessor {@Overridepublic Feed process(String feed) {System.out.println("processing this google+ feed");// processing logicsreturn new Feed(feed);}}
我将通过此处所述的自定义限定符对这2个bean进行注释
@javax.inject.Qualifier
@java.lang.annotation.Retention(RUNTIME)
@java.lang.annotation.Target({FIELD, PARAMETER, TYPE})
@java.lang.annotation.Documented
public @interface FeedProcessor {
}
然后用它注释我的两个处理器。
@FeedProcessor
public class TwitterFeedProcessor implements SocialFeedProcessor{@Overridepublic Feed process(String feed) {System.out.println("processing this twitter feed");// processing logicsreturn new Feed(feed);}}
@FeedProcessor
public class GooglePlusFeedProcessor implements SocialFeedProcessor {@Overridepublic Feed process(String feed) {System.out.println("processing this google+ feed");// processing logicsreturn new Feed(feed);}}
没什么特别的,但是现在当我们编写装饰器时,我们使用CDI的功能仅使用@FeedProcessor批注装饰类。
@Decorator
public class SocialFeedDecorator implements SocialFeedProcessor {@Delegateprivate @FeedProcessor SocialFeedProcessor processor;@Overridepublic Feed process(String feed) {System.out.println("our decorator is decorating");return processor.process(feed);}
}
剩下的唯一事情就是在beans.xml中注册装饰器
<decorators><class>be.styledideas.blog.decorator.SocialFeedDecorator</class>
</decorators>
通过使用注释,我们可以使用此装饰器自动装饰我们的SocialfeedProcessor的所有实现。 当我们添加不带注释的SocialFeedProcessor的额外实现时,将不装饰Bean。
参考: Java EE6装饰器,在注入时装饰类, Java EE6装饰器,来自Styled Ideas Blog的 JCG合作伙伴 Jelle Victoor的 高级用法 。
- JDK中的设计模式
- 在域驱动设计中使用状态模式
- 基本的EJB参考,注入和查找
- 使用Spring AOP进行面向方面的编程
- 使用Spring AspectJ和Maven进行面向方面的编程
翻译自: https://www.javacodegeeks.com/2011/10/java-ee6-decorators-decorating-classes.html
java与java ee