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.可能会出一些奇怪的问题.根本上,同时用这两种方式就是错误的.

CDI services--Decorators(装饰器)的更多相关文章

  1. CDI Services *Decoretions *Intercepters * Scope * EL\(Sp EL) *Eventmodel

    1.Decorators装饰器综述 拦截器是一种强大的方法在应用程序捕捉运行方法和解耦.拦截器可以拦截任何java类型的调用.  这使得拦截器适合解决事务管理,安全性,以及日记记录.  本质上说,拦截 ...

  2. Python入门笔记(19):Python函数(2):函数/方法装饰器

    一.装饰器(decorators) 装饰器的语法以@开头,接着是装饰器函数的名字.可选参数. 紧跟装饰器声明的是被装饰的函数和被装饰的函数的可选参数,如下: @decorator(dec_opt_ar ...

  3. Python全栈工程师(装饰器、模块)

    ParisGabriel                每天坚持手写  一天一篇  决定坚持几年 全栈工程师     Python人工智能从入门到精通 装饰器 decorators(专业提高篇) 装饰 ...

  4. BehaviorTree.CPP行为树BT的装饰器节点(五)

    Decorators 装饰器是只能有一个子项的节点. 由装饰者来决定是否,何时以及对子节点进行tick. InverterNode tick子节点一次,如果子节点失败则返回SUCCESS,如果孩子成功 ...

  5. 通过decorators = [,] 的形式给类中的所有方法添加装饰器

    给类添加装饰器有多种方法: 1.可以在类中的某个方法上边直接@添加,这个粒度细.无需详细介绍 2.也可以在类中通过 decorators=[, ]的形式添加,这样的话,类中的所有方法都会被一次性加上装 ...

  6. TypeScript学习笔记(九):装饰器(Decorators)

    装饰器简介 装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式. 需要注意的是:装饰器是一项实验性特性,在未来的版本中可能会发生改变. 若要启用实验性的装饰器特 ...

  7. Python装饰器(Decorators )

    http://book.pythontips.com/en/latest/decorators.html 在<Built-in Functions(3.6)>和<Python上下文管 ...

  8. 【低门槛 手把手】python 装饰器(Decorators)原理说明

    本文目的是由浅入深地介绍python装饰器原理 装饰器(Decorators)是 Python 的一个重要部分 其功能是,在不修改原函数(类)定义代码的情况下,增加新的功能 为了理解和实现装饰器,我们 ...

  9. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

随机推荐

  1. Doctirne---查询更新等操作

    使用Doctrine进行mysql更删改查操作,事务处理,生命周期的管理 1.先记录最简单的插入操作 $em = $this->getDoctrine()->getManager(); / ...

  2. 美团小程序框架mpvue入门

    mpvue 主要特性 使用 mpvue 开发小程序,你将在小程序技术体系的基础上获取到这样一些能力: 1. 彻底的组件化开发能力:提高代码复用性 2. 完整的 Vue.js 开发体验 3. 方便的 V ...

  3. C# 数据为空,不能对NULL调用此方法或属性的解决办法

    在运行C#项目时,报出了以下错误,错误原因是数据库中的值为null时,查询时会触发该错误提示 部分源代码如下: public List<Student> findData2() { ; / ...

  4. (三)ajax请求不同源之cors跨域

    一.基本原理 CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)它允许浏览器向跨源服务器,发出 XMLHttpReque ...

  5. LINUX更改桌面的分辨率

    命令行 输入xrandr 输入xrandr命令后可以看到系统的一些分辨率的列表, 和当前系统屏幕的分辨率信息,可以通过命令的 相应参数对系统分辨率的一些设置操作. xrandr -s 0 全屏 xra ...

  6. PYTOGO之旅——环境搭建

    Go 语言支持以下系统: Linux FreeBSD Mac OS X(也称为 Darwin) Windows 安装包下载地址为:https://golang.org/dl/. 如果打不开可以使用这个 ...

  7. 小甲鱼Python第十九讲课后习题

    笔记: 1.内嵌函数:函数内部新创建另一个函数 2.闭包:函数式编程的重要语法,如果在一个内部函数里,对外部作用域(但不是在全局作用域的变量)进行引用,那么内部函数就会被认为是闭包. 3.nonloc ...

  8. vue_ajax 请求

    yarn add vue-resource axios npm install --save axios pubsub-js // import VueResource from "vue- ...

  9. (AB)Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round

    A. Right-Left Cipher time limit per test 1 second memory limit per test 256 megabytes input standard ...

  10. apt-get安装mysql

    1,检查是否已安装. 2,安装: apt-get install mysql-client-core-5.5 apt-get install mysql-server mysql-client 安装过 ...