2012-07-09 48 views
17

这是一个Hibernate的Spring MVC项目。 我试图创建一个Logger类,负责将日志输入到数据库中。 其他类只是调用具有某些属性的适当方法,而这个类应该做所有的魔术。 本质上它应该是一个带有静态方法的类,但是会导致autowiering dao对象出现问题。@ututowired静态类

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无法在静态对象上工作,因为它们被创建为早期自动创建机制还没有创建。

回答

38

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

@Component 
public class StatisticLogger { 

    private static Dao dao; 

    @Autowired 
    private Dao dao0; 

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

} 

在一个字,一个@Autowired实例字段,并赋值给静态当你的对象被创建申请。顺便说一下,StatisticLogger对象也必须由Spring来管理。

+0

有趣招。我将在未来中记住这一点:) – 2014-03-23 14:39:57

+0

该方法的返回类型必须是无效的。 http://docs.oracle.com/javaee/5/api/javax/annotation/PostConstruct.html – 2014-06-12 11:44:52

+1

在战斗结束后不久,我就开始使用这个解决方案,这个解决方案大部分工作。但是Sonar公司很快给了我一个警告:“从非静态方法正确更新静态字段很难正确使用,如果有多个类实例和/或多个线程在场,很容易导致错误。理想情况下,静态字段只能从同步静态方法更新。“我认为值得一提。 – MaxouMask 2017-01-19 09:42:26

14

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

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

+0

好的,谢谢 – 2016-04-05 04:46:45

0

我知道这是一个老问题,但只是想分享我做什么, 由@Weibo李的解决方案是好的,但问题也引起了人们对静态变量

分配非静态变量声纳关键警报我没有声纳警报解决它的方法如下

  1. 我改变StatisticLogger到singlton类(不再是静态的) 这样

    公共类Statisti cLogger {私人静态StatisticLogger实例=空; 私人刀道;

    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的服务的服务(或组件)做任何事情都要和平均低于PostConstruct方法总是调用之前什么都可以访问StatisticLogger 像这样

    @Component 公共类DaoSetterService {

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

    }

  3. 而不是使用StatisticLogger作为静态类的我只是把它作为StatisticLogger.getInstance(),我可以访问它里面的所有方法