回答
這就是你通常使用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