zoukankan      html  css  js  c++  java
  • CDI services--Decorators(装饰器)

    1.Decorators装饰器综述

    拦截器是一种强大的方法在应用程序捕捉运行方法和解耦。拦截器可以拦截任何java类型的调用. 
    这使得拦截器适合解决事务管理,安全性,以及日记记录. 
    本质上说,拦截器并不知道他们截获的实际语义事件.因此,拦截器并不是很适合和系统的业务挂钩. 

    而本章的装饰器,则又不一样. 
    装饰器只截取调用某个Java接口,因此获知这个接口的所有语义连接。 
    decorator直接实现与业务语义操作,这也意味着装饰没有拦截器的通用性。 
    拦截器和修饰符,尽管在很多方面相似,是互补的。但decorator无法解决技术问题,横跨许多不同的类型。 

    假设我们有一个接口,代表账户: 

    1
    2
    3
    4
    5
    6
    public interface Account {
       public BigDecimal getBalance();
       public User getOwner();
       public void withdraw(BigDecimal amount);
       public void deposit(BigDecimal amount);
    }

    几种不同的Bean在我们系统实现账户接口。

    然而,我们有一个强制要求:任何类型的账户,交易必须由系统日志进行记录. 
    这就是装饰器的一个工作. 

    用@Decorator标注一个bean(甚至可能是一个抽象类),这样就表明此类是装饰器. 

    1
    2
    3
    4
    @Decorator
    public abstract class LargeTransactionDecorator implements Account {
       ...
    }

    装饰器的装修类型实现方法,可以让他拦截他想要拦截的.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Decorator
    public abstract class LargeTransactionDecorator implements Account {
     
       @Inject @Delegate @Any Account account;
     
       @PersistenceContext EntityManager em;
         
       public void withdraw(BigDecimal amount) {
          ...
       }
      
       public void deposit(BigDecimal amount);
          ...
       }
    }

    需要注意的是,一个装饰器可能是一个抽象类. 因此,某些情况下你可能不需要去实现方法.

    2.Delegate object(委托对象)

    decorator有特殊的注射点,称为委托注入点(delegate injection point), 
    其必须有一个delegate injection point,可以是一个构造函数参数,初始化方法参数或injected field. 

    1
    2
    3
    4
    5
    6
    @Decorator
    public abstract class LargeTransactionDecorator implements Account {
     
       @Inject @Delegate @Any Account account;
       ...
    }

    像上面这段代码,装饰器将绑定到所有实现了Account的Bean上.

    如果是下面这段代码,@Foreign是我们自定义. 
    那么装饰器将绑定到实现了Account的Bean并且qualifiers是@Foreign的Bean上. 

    1
    2
    3
    4
    5
    6
    @Decorator
    public abstract class LargeTransactionDecorator implements Account {
     
       @Inject @Delegate @Foreign Account account;
       ...
    }

    decorator可能调用委托对象,和拦截器调用InvocationContext.proceed() 有大致有相同的结果.但主要的区别在于装饰可以委托对象上调用任何业务方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    @Decorator
    public abstract class LargeTransactionDecorator implements Account {
     
       @Inject @Delegate @Any Account account;
     
       @PersistenceContext EntityManager em;   
     
       public void withdraw(BigDecimal amount) {
     
          account.withdraw(amount);
          if ( amount.compareTo(LARGE_AMOUNT)>0 ) {
             em.persist( new LoggedWithdrawl(amount) );
          }
       }
         
       public void deposit(BigDecimal amount);
     
          account.deposit(amount);
          if ( amount.compareTo(LARGE_AMOUNT)>0 ) {
     
             em.persist( new LoggedDeposit(amount) );
          }
       }
    }

    3.Enabling decorators(启用装饰器)

    默认情况下,所有装饰器都是禁用的.推荐用bean.xml进行开启.bean.xml是第一优先的.其次才是@Priority. 
    CDI 1.1以后的decorator可以使用@Priority开启。@Priority定义了装饰器和拦截器的优先顺序,但还是没bean.xml里直观. 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <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">
     
       <decorators>
             <class>org.mycompany.myapp.LargeTransactionDecorator</class>
       </decorators>
    </beans>

    注意:不要即在bean.xml配置又写@Priority.可能会出一些奇怪的问题.根本上,同时用这两种方式就是错误的.

  • 相关阅读:
    wp8.1 Study14 FilePicker简单介绍
    wp8.1 Study13:在WP8.1中分享文件和数据
    WP8.1 Study12:文件压缩与Known Folder(包含SD卡操作)
    wp8.1 Study9:针对不同的屏幕和手机方向调整UI
    wp8.1 Study11:APP里文件读写和使用XML和Json序列化
    wp8.1 Study10:APP数据存储
    wp8.1 C#技巧: 计时器
    wp8.1 Study8:页面过渡和主题动画(Page transition and Theme animations)
    2、IValueConverter应用
    1、ViewModel类的构建和INoyifyPropertyChanged的应用
  • 原文地址:https://www.cnblogs.com/formyfish/p/10752005.html
Copyright © 2011-2022 走看看