回答
这就是你通常使用AOP的方式,而不是手动编写和包装实现(而不是你不能这么做)。
对于使用Guice的AOP,您希望创建交易MethodInterceptor
和日志记录MethodInterceptor
,然后使用bindInterceptor(Matcher, Matcher, MethodInterceptor)
来设置应拦截哪些类型和方法。第一个Matcher
匹配要拦截的类型,第二个匹配拦截的方法。可以是Matchers.any()
,匹配类型或方法(@Transactional
,说)或任何你想要的特定注释。匹配方法将被截取并自动处理。装饰者模式基本上有很多样板。
做手工,一个办法是:
class ServiceModule extends PrivateModule {
@Override protected void configure() {
bind(Service.class).annotatedWith(Real.class).to(RealService.class);
}
@Provides @Exposed
protected Service provideService(@Real Service service) {
return new LoggingService(new TransactionalService(service));
}
}
可以一起使用@Named
与@Inject
指定要注入哪个Bean。
一个简单的例子有注射服务:
而且相应的事务装饰类:
@org.springframework.stereotype.Service("transactionDecorator")
public class ServiceDecoratorTransactionSupport extends ServiceDecorator {
@Inject
@Named("serviceBean")
public ServiceDecoratorTransactionSupport(Service service) {
super(service);
}
}
这暴露了你的配置到你的代码,所以我会建议做的装饰逻辑一个@Configuration
类,并注释例如与@Primary
日志记录服务。用这种方法你的测试类可以是这个样子:
public class ServiceTest {
@Inject
private Service service;
而且配置类:
@Configuration
public class DecoratorConfig {
@Bean
@Primary
public ServiceDecorator serviceDecoratorSecurity() {
return new ServiceDecoratorSecuritySupport(
serviceDecoratorTransactionSupport());
}
@Bean
public ServiceDecorator serviceDecoratorTransactionSupport() {
return new ServiceDecoratorTransactionSupport(serviceBean());
}
@Bean
public Service serviceBean() {
return new ServiceImpl(serviceRepositoryEverythingOkayStub());
}
@Bean
public ServiceRepository serviceRepositoryEverythingOkayStub() {
return new ServiceRepositoryEverythingOkStub();
}
}
我的第二个示例不公开有关其实施将返回的任何细节,但它取决于几个Spring特定的类。
您也可以结合使用这两种解决方案。例如,在装饰器上使用Spring的@Primary
注释,并让Spring将此装饰器注入给定类型的实例中。
@Service
@Primary
public class ServiceDecoratorSecuritySupport extends ServiceDecorator {
}
@Target(PARAMETER)
@Retention(RUNTIME)
@BindingAnnotation
public @interface Decorate {
Class<?> value();
}
/* see com.google.inject.name.NamedImpl for rest of
the methods DecorateImpl must implement */
public class DecorateImpl implements Decorate, Serializable {
private final Class<?> value;
private DecorateImpl(Class<?> val) {
value = val;
}
public static Decorate get(Class<?> clazz) {
return new DecorateImpl(clazz);
}
public Class<?> value() {
return value;
}
...
...
}
这里是如何使用它:
public interface ApService {
String foo(String s);
}
public class ApImpl implements ApService {
private final String name;
@Inject
public ApImpl(@Named("ApImpl.name") String name) {
this.name = name;
}
@Override
public String foo(String s) {
return name + ":" + s;
}
}
第一装饰:
public class ApDecorator implements ApService {
private final ApService dcrtd;
private final String name;
@Inject
public ApDecorator(@Decorate(ApDecorator.class) ApService dcrtd,
@Named("ApDecorator.name") String name) {
this.dcrtd = dcrtd;
this.name = name;
}
public String foo(String s) {
return name + ":" + s + ":"+dcrtd.foo(s);
}
}
二装饰:
public class D2 implements ApService {
private final ApService dcrt;
@Inject
public D2(@Decorate(D2.class) ApService dcrt) {
this.dcrt = dcrt;
}
@Override
public String foo(String s) {
return "D2:" + s + ":" + dcrt.foo(s);
}
}
public class DecoratingTest {
@Test
public void test_decorating_provider() throws Exception {
Injector inj = Guice.createInjector(new DecoratingModule());
ApService mi = inj.getInstance(ApService.class);
assertTrue(mi.foo("z").matches("D2:z:D:z:I:z"));
}
}
模块:
class DecoratingModule extends AbstractModule {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named("ApImpl.name")).to("I");
bindConstant().annotatedWith(Names.named("ApDecorator.name")).to("D");
bind(ApService.class).
annotatedWith(DecorateImpl.get(ApDecorator.class)).
to(AnImpl.class);
bind(ApService.class).
annotatedWith(DecorateImpl.get(D2.class)).
to(ApDecorator.class);
bind(ApService.class).to(D2.class);
}
}
如果绑定配置看起来很丑,可以创建看起来不错的Builder/DSL。
缺点是(与手动链构建相比),无法将同一模块链接两次(即D2-> D2-> D1-> Impl)和构造函数params中的样板。
上面显示的绑定配置确实看起来很丑。你可以看看[decorice](https://github.com/beluchin/decorice)来解决模板问题。 – beluchin 2015-05-29 21:37:24
- 1. QGraphicsView和装饰器模式
- 2. StructureMap和装饰器模式
- 3. 装饰模式
- 4. 装饰模式装饰器限制
- 5. Python装饰器和装饰器模式有什么区别?
- 6. 装饰模式与继承和组合
- 7. C++游戏和装饰模式
- 8. Dojo小部件和装饰模式?
- 9. JavaScript的装饰模式
- 10. AS3/Flex装饰模式
- 11. 显示装饰模式
- 12. 精细的装饰模式
- 13. 装饰模式在smalltalk
- 14. 装饰模式vs列表
- 15. 柔性装饰模式?
- 16. Decorator模式 - 从装饰
- 17. 装饰设计模式
- 18. 装饰模式帮助
- 19. 装饰模式问题?
- 20. C++中的装饰模式
- 21. 装修模式中的装饰顺序
- 22. 如何从装饰模式中删除装饰对象Java中的模式
- 23. 装饰模式问题 - 如何调用嵌套装饰方法?
- 24. Python中的装饰器必须实现装饰器模式吗?
- 25. 装饰者模式 - 如何一次装饰两种类型
- 26. 为什么在装饰设计模式命名为“装饰”?
- 27. 装饰模式与装饰特定的方法在Java
- 28. JPA和修饰模式
- 29. AngularJS。装饰模型
- 30. 使用装饰器匹配模式
感谢您的回答。我实际上使用Spring,所以对我来说这是不可能的,我只想使用'javax.inject'包。但无论如何,这很好。 – 2010-06-30 14:52:35