2016-07-15 10 views
1

アプリケーションを開始するとすぐにファクトリでクラス(クラスのインスタンスではない)を登録するアノテーションを実装したいと思います。私はSpring Framework 4.2.7を使用しています。Springでカスタム注釈を実装する

ダッシュボードと複数のウィジェットを備えたシステムを考えてみましょう。ダッシュボードには、現在のユーザーに対して表示するウィジェットのリストを含む設定ファイルがあります。表示されると、設定を読み取り、ウィジェットを作成します。ウィジェットは設定から​​追加のパラメータを受け取ります。ここで

は、コードのビットは、このことを示す図である:私のウィジェットを実装する場合

public class TestDashboard implements Dashboard { 
    public void dashboardPreDisplay() { 
     List<String> widgets = getWidgetList(/* current user in session */); 
     for (String widgetId : widgets) { 
      // create instance of DashboardWidget with given ID 
      DashboardWidget x = widgetFactory.createWidget(widgetId); 
     } 
    } 

    public List<String> getWidgetList(String user) { 
     // load list of IDs of DashboardWidgets to be displayed for the user 
    } 

    @Autowired 
    private WidgetFactory widgetFactory; 
} 

@Service 
public class WidgetFactory { 
    public DashboardWidget createWidget(String widgetId) { 
     // look up Class<> of DashboardWidget with given id in widgetClasses 
     // construct and initialize DashboardWidget 
    } 

    private HashMap<String, Class<?>> widgetClasses; 
} 

私は、ファクトリクラスでウィジェットを登録するに対処する必要はありません。ウィジェットはcreateWidget-法を与えることによって構築することができるように、アプリケーションは、それが@DashboardWidget注釈のためのクラスパスをスキャンし、工場を持つクラスを登録する必要が開始すると

@DashboardWidget(id = "uniqueId") 
public class DashboardWidgetA implements DashboardWidget { 
    // ... 
} 

:理想的には私はちょうどそのようなウィジェットに注釈を付けるだろうウィジェットのID。

私はちょっと混乱しています。私は、Springにはこの動作を達成するためのあらゆるツールが搭載されていると思います。しかし、私はそれをする方法を考えることができません。

私に助言がありますか?

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface DashboardWidget {} 

は、その後、あなたのウィジェットのクラスに注釈を付け、それらのSpring Beanにすることができます。

答えて

1

何もカスタムアノテーションを作成するために防ぎません。シングルトン(スコープ=シングルトン)として、またはユーザーごとに別々のインスタンス(スコープ=プロトタイプ)として使用する場合は、注意する必要があります。あなたが実装する必要が

public class WidgetInitializationListener implements ApplicationListener<ContextRefreshedEvent> { 

@Override 
public void onApplicationEvent(ContextRefreshedEvent event) { 

    ApplicationContext context = event.getApplicationContext(); 
    String[] beanDefinitionNames = context.getBeanDefinitionNames(); 
    for (String beanDefinitionName : beanDefinitionNames) { 
     String originalClassName = getOriginalClassName(beanDefinitionName, event); 
     if (originalClassName != null) { 
      Class<?> clazz = Class.forName(originalClassName); 
      if (hasWidgetAnnotation(clazz)) { 
       registerSomewhereYourWidget(context, beanDefinitionName, originalClassName); 
      } 
     } 
    } 
} 

private String getOriginalClassName(String name, ContextRefreshedEvent event) { 
    try { 
     ConfigurableListableBeanFactory factory = 
       (ConfigurableListableBeanFactory)event.getApplicationContext().getAutowireCapableBeanFactory(); 
     BeanDefinition beanDefinition = factory.getBeanDefinition(name); 
     return beanDefinition.getBeanClassName(); 
    } catch (NoSuchBeanDefinitionException e) { 
     LOG.debug("Can't get bean definition for : " + name); 
     return null; 
    } 
} 

をだから、ほとんどがここでは、あなただけの注釈付きのものを見つけるためにあなたの豆を介して実行を除いて春とは何の関係もありません。

+0

Hey Igor、アプリケーションイベントを私に指摘してくれてありがとう。私はこの答えを受け入れるだろう:) – gdiquest

関連する問題