【问题标题】:HowTo extend Spring Annotation @Transactional如何扩展 Spring 注解 @Transactional
【发布时间】:2011-04-06 04:30:03
【问题描述】:

我必须在我的 web 应用程序中使用 3 个不同的事务管理器。于是我按照Spring reference(10.5.6.3节自定义快捷方式注解)编写了自己的Annotation。

一个注解(用于使用一个特定的事务管理器)如下所示:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.transaction.annotation.Transactional;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional("customer")
public @interface CustomerTX{


}

使用自定义的@CustomerTX 注释注释我的服务层时,一切正常。但是我必须为我的注解提供更多的选项,比如 readonly=true、rollbackFor= 等等。由于您不能“扩展”注释(我真的只需要从 Spring 扩展 @Transactional 注释),因此正确的实现是什么?

【问题讨论】:

    标签: java spring annotations transactional


    【解决方案1】:

    恐怕您必须为每个用例创建几个自定义注释,并使用您需要的确切 @Transactional 注释对每个注释进行注释。

    或者您必须在 AspectJ 中编写自己的切面(从 spring-aspects.jar 扩展 org.springframework.transaction.aspectj.AbstractTransactionAspect)来创建自己的事务逻辑。


    更新:这在当时是正确的答案,但从 Spring 4 起,the answer by C.L.S 应该是首选

    【讨论】:

    • 你真的是说我必须写这样的东西(假设我只想将事务设置为只读):@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy .RUNTIME) @Transactional(value="customer",readOnly=true) public @interface CustomerTXReadonly{ } 这不可能是唯一可行的解​​决方案...
    • 恐怕是这样,因为注释的限制。正如我所说:要么写你自己的方面(我更喜欢)
    • 感谢您的帮助。我会尝试写我自己的方面。可惜注解不可扩展:(
    • 获取一份AspectJ in Action:manning.com/laddad 这是一本非常好的关于 AspectJ 有无 Spring 的书
    • 您能否详细说明“或者您必须在 AspectJ 中编写自己的方面(从 spring-aspects.jar 扩展 org.springframework.transaction.aspectj.AbstractTransactionAspect)来创建自己的事务逻辑。 "这是怎么做到的?谢谢
    【解决方案2】:

    在春季 4 中,您可以做到这一点。如documentation中所述

    元注释也可以组合起来创建组合注释。比如Spring MVC中的@RestController注解就是由@Controller和@ResponseBody组成的。

    此外,组合注释可以选择性地从元注释重新声明属性以允许用户自定义。当您只想公开元注释属性的子集时,这可能特别有用。例如,Spring 的 @SessionScope 注解将作用域名称硬编码为 session,但仍允许自定义 proxyMode。

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Scope(WebApplicationContext.SCOPE_SESSION)
    public @interface SessionScope {
    
        /**
         * Alias for {@link Scope#proxyMode}.
         * <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.
         */
        @AliasFor(annotation = Scope.class)
        ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
    
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-18
      • 2014-12-24
      • 1970-01-01
      • 1970-01-01
      • 2021-02-11
      • 1970-01-01
      • 2019-09-20
      • 2014-04-03
      • 2014-07-18
      相关资源
      最近更新 更多