[weld] 问题专家interceptor哥
wuhaixing
2010-04-22
Interceptor的能力是在Java Interceptors规范中定义的. CDI用更复杂的、更语义化的、基于注解的方式对他进行了武装,让罩着bean的interceptor更强大。
Interceptors规范定义了两种拦截方式:
另外EJB规范还定义了一个timeout方法拦截。 当宣称成为interceptor哥小弟的业务方法被调用时,interceptor会现身: public class TransactionInterceptor { @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... } } 当container调用bean的生命周期回调方法时,interceptor哥也敢上: public class DependencyInjectionInterceptor { @PostConstruct public void injectDependencies(InvocationContext ctx) { ... } } interceptor哥可以身兼多职,即可以拦截业务方法,也可以同时拦截生命周期回调方法。 timeout 方法的 interceptor会在container调用EJB的timeout方法是发挥作用: public class TimeoutInterceptor { @AroundTimeout public Object manageTransaction(InvocationContext ctx) throws Exception { ... } } |
|
wuhaixing
2010-04-22
如何成为interceptor哥的小弟
常年写程序,总有需要事务处理的时候。你也知道这个问题可以交给interceptor哥。但首先你得先有个标,官方称谓是interceptor binding type。让你的bean带上这个标,interceptor哥就会认得他是自己人了。 @InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Transactional {} 给带上: @Transactional public class ShoppingCart { ... } 当然,你也可以只给某个方法带标: public class ShoppingCart { @Transactional public void checkout() { ... } } |
|
wuhaixing
2010-04-22
interceptor哥是如何练成的
搞了这么久,还没见过interceptor哥究竟长什么样呢.其实他不神秘,他也带标。不过大哥有大哥的风范,头上还得有个@Interceptor。 @Transactional @Interceptor public class TransactionInterceptor { @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... } } 哦,他也是container的子民,能用DI。 @Transactional @Interceptor public class TransactionInterceptor { @Resource UserTransaction transaction; @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... } } 老大们很河蟹,一个标可以多个人带(根据配置决定出场次序)。 |
|
wuhaixing
2010-04-22
interceptor哥的营业执照
interceptor毕竟是个压力比较大的职业,一般是不让干的。想干的话,得在beans.xml里注册一下。注意,这个注册在beans.xml所在的archive外是不被承认的。 <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"> <interceptors> <class>org.mycompany.myapp.TransactionInterceptor</class> </interceptors> </beans> 熟悉的尖括号的味道! XML配置在这里出现帮我们解决了两个问题:
比如你可以让安全哥比事务哥先出场。 <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"> <interceptors> <class>org.mycompany.myapp.SecurityInterceptor</class> <class>org.mycompany.myapp.TransactionInterceptor</class> </interceptors> </beans> 如果你开发测试的时候想让他们俩都休息,只要别在beans.xml里提他们就行了。 |
|
wuhaixing
2010-04-22
可以用member选择让哪个interceptor哥出场
有时候你可能会觉得@Transactional标过于简单,表达能力太弱。像所有其他的标一样,你可以给他加member: @InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Transactional { boolean requiresNew() default false; } member值不同的标意味着跟的是不同的大哥,CDI会根据requiresNew的值来判断你到底是想要TransactionInterceptor罩你,还是想让RequiresNewTransactionInterceptor罩你。 @Transactional(requiresNew = true) @Interceptor public class RequiresNewTransactionInterceptor { @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... } } 想用RequiresNewTransactionInterceptor,就这样 @Transactional(requiresNew = true) public class ShoppingCart { ... } 如果你只有一个interceptor,并且想让container忽略requiresNew的值,可以用@Nonbinding: @InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Secure { @Nonbinding String[] rolesAllowed() default {}; } |
|
wuhaixing
2010-04-22
可以召唤多个interceptor哥
看代码吧 @Secure(rolesAllowed="admin") @Transactional public class ShoppingCart { ... } 可以合体,注意不是标合体 @Transactional @Secure @Interceptor public class TransactionalSecureInterceptor { ... } 标可以不在一起,下面几种情况召唤的都是上面这个interceptor public class ShoppingCart { @Transactional @Secure public void checkout() { ... } } @Secure public class ShoppingCart { @Transactional public void checkout() { ... } } @Transactional public class ShoppingCart { @Secure public void checkout() { ... } } @Transactional @Secure public class ShoppingCart { public void checkout() { ... } } |
|
wuhaixing
2010-04-22
其实标也可以合体
java语言不支持annotations的继承。但实际上总会有需要重用的时候,比如你可能需要这样的东西: public @interface Action extends Transactional, Secure { ... } CDI可以提供等效的注解,把多个annotation绑定到一个annotation上。 @Transactional @Secure @InterceptorBinding @Target(TYPE) @Retention(RUNTIME) public @interface Action { ... } 这样,打上@Action 的标的会关联到TransactionInterceptor 和SecurityInterceptor. (如果有TransactionalSecureInterceptor,也可以) |
|
wuhaixing
2010-04-22
@Interceptors能用,但还是别用了。
|
|
javaeye_mao
2010-04-26
别迷恋哥!!!!
|
|
lonvea
2010-04-26
wuhaixing 写道 @Interceptors能用,但还是别用了。
哥们, 你给我说说,interceptor中抛出异常,系统如何捕获??特别是在JSF中?? 一半你浏览一个页面时,如果没有权限就会跳转到“无权限”页面。。。 @Inject public UserAO(){ .... userBO.findAllUser(); } findAllUser()被拦截器拦截。。。 |