@autowired在静态类中

时间:2012-07-09 09:51:45

标签: spring hibernate spring-mvc autowired static-class

这是一个带有Hibernate的Spring MVC项目。 我正在尝试创建一个Logger类,负责将日志输入数据库。 其他类只调用具有一些属性的正确方法,这个类应该做所有的魔术。 本质上它应该是一个具有静态方法的类,但这会导致autoiering 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? 我知道我可以将它作为方法参数传递,但这不是很好。 我猜测autowired无法在静态对象上工作,因为它们是为早期创建的,所以还没有创建自动维护机制。

4 个答案:

答案 0 :(得分:52)

你不能@Autowired一个静态字段。但是处理这个问题有一个棘手的技巧:

@Component
public class StatisticLogger {

  private static Dao dao;

  @Autowired
  private Dao dao0;

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

}

总之,@Autowired一个实例字段,并在构造对象时将值赋给静态字段。顺便说一句,StatisticLogger对象也必须由Spring管理。

答案 1 :(得分:16)

古典自动装配可能不起作用,因为静态类不是Bean,因此不能由Spring管理。有很多方法可以解决这个问题,例如使用the factory-method aproach in XML,或者通过在静态初始化程序块中加载Spring上下文中的bean,但我建议改变你的设计:

不要使用静态方法,使用您需要的服务。如果你使用Spring,你也可以正确使用它。依赖注入是一种面向对象的技术,只有你实际拥抱OOP才有意义。

答案 2 :(得分:0)

我知道这是一个老问题,但只想分享我的所作所为, @Weibo Li的解决方案还可以,但问题是它引发了关于将非静态变量分配给静态变量的Sonar Critical警告

我解决它没有声纳警报的方式如下

  1. 我将StatisticLogger更改为singlton类(不再是静态的) 像这样

    公共类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类中设置它 这是安全的,因为在Spring中它将在执行任何其他操作之前初始化所有托管bean,这意味着在任何可以访问StatisticLogger之前始终调用下面的PostConstruct方法 像这样的东西

    @Component 公共类DaoSetterService {

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

    }

  3. 我没有将StatisticLogger用作静态类,而只是将其用作StatisticLogger.getInstance(),我可以访问其中的所有方法

答案 3 :(得分:0)

您可以将DAO从调用它的地方传递给StatisticLogger

public static void AddLoginEvent(LogStatisticBean user, DAO dao){
    dao.callMethod();
}
相关问题