web-dev-qa-db-ja.com

静的クラスの@autowired

これは、Hibernateを使用したSpring MVCプロジェクトです。私は、データベースにログを入力するLoggerクラスを作成しようとしています。他のクラスはいくつかの属性を持つ適切なメソッドを呼び出すだけであり、このクラスはすべての魔法を実行する必要があります。本来は静的メソッドを持つクラスである必要がありますが、daoオブジェクトの自動配線で問題が発生します。

public class StatisticLogger {
    @Autowired
    static Dao dao;
    public static void AddLoginEvent(LogStatisticBean user){
        //TODO code it god damn it
    }
    public static void AddDocumentEvent(LogStatisticBean user, Document document, DocumentActionFlags actionPerformed){
        //TODO code it god damn it
    }
    public static void addErrorLog(Exception e, String page,  HashMap<String, Object> parameters){
        ExceptionLogBean elb=new ExceptionLogBean();
        elb.setStuntDescription(e);
        elb.setSourcePage(page);
        elb.setParameters(parameters);
        if(dao!=null){ //BUT DAO IS NULL
            dao.saveOrUpdateEntity(elb);
    }
}

それを正しくする方法は? daoオブジェクトをnullにしないために何をすべきですか?メソッドパラメータとして渡すことができることは知っていますが、それはあまり良くありません。自動配線は静的オブジェクトでは動作しないと思います。なぜなら、自動配線メカニズムはまだ作成されていないためです。

21
T.G

@Autowired静的フィールド。しかし、これに対処するためのトリッキーなスキルがあります。

@Component
public class StatisticLogger {

  private static Dao dao;

  @Autowired
  private Dao dao0;

  @PostConstruct     
  private void initStaticDao () {
     dao = this.dao0;
  }

}

一言で、 @Autowiredインスタンスフィールド、およびオブジェクトの構築時に値を静的フィールドに割り当てます。ところで、StatisticLoggerオブジェクトもSpringで管理する必要があります。

54
Weibo Li

静的クラスはBeanではないため、Springで管理できないため、従来の自動配線はおそらく機能しません。これを回避する方法があります。たとえば、 the factory-method aproach in XML 、または静的イニシャライザブロックのSpringコンテキストからBeanをロードすることにより、設計を変更することをお勧めします。

静的メソッドを使用せず、必要な場所に注入するサービスを使用します。 Springを使用する場合、正しく使用することもできます。依存性注入はオブジェクト指向の手法であり、実際にOOPを採用する場合にのみ意味があります。

18

私はこれが古い質問であることを知っていますが、私がやったことを共有したかっただけです、@ Weibo Liによる解決策は大丈夫ですが、それは非静的変数を静的変数に割り当てることに関するソナークリティカルアラートを発生させる問題です

ソナーアラートなしで解決した方法は次のとおりです

  1. このようにStatisticLoggerをシングルトンクラス(静的ではない)に変更します

    パブリッククラスStatisticLogger {private static StatisticLogger instance = null;プライベートダオダオ;

    public static StatisticLogger getInstance() {
        if (instance == null) {
            instance = new StatisticLogger();
        }
        return instance;
    }
    
    protected StatisticLogger() {
    }
    
    public void setDao(Dao dao) {
        this.dao = dao;
    }
    public void AddLoginEvent(LogStatisticBean user){
        //TODO code it god damn it
    }
    public void AddDocumentEvent(LogStatisticBean user, Document document, DocumentActionFlags actionPerformed){
        //TODO code it god damn it
    }
    public  void addErrorLog(Exception e, String page,  HashMap<String, Object> parameters){
        ExceptionLogBean elb=new ExceptionLogBean();
        elb.setStuntDescription(e);
        elb.setSourcePage(page);
        elb.setParameters(parameters);
        if(dao!=null){ 
            dao.saveOrUpdateEntity(elb);
    }
    

    }

  2. 私は欲しいサービスを自動配線するサービス(またはコンポーネント)を作成し、singltonクラスに設定しますこれは春に他の何かをする前にすべてのマネージドBeanを初期化するので安全ですどんなものでもStatisticLoggerに次のようにアクセスできます

    @Component public class DaoSetterService {

    @Autowired
    private Dao dao0;
    
    @PostConstruct     
    private void setDaoValue () {
        StatisticLogger.getInstance().setDao(dao0);
    }
    

    }

  3. StatisticLoggerを静的クラスとして使用する代わりに、StatisticLogger.getInstance()として使用するだけで、その中のすべてのメソッドにアクセスできます。

0
Hani