Spring MVC @在静态类中自动连接

3gtaxfhh  于 2023-01-26  发布在  Spring
关注(0)|答案(5)|浏览(197)

这是一个带有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对象为空呢?我知道我可以把它作为一个方法参数传递,但是那不是很好。我猜autowired不能在静态对象上工作,因为它们创建得太早,autowired机制还没有创建。

vm0i2vca

vm0i2vca1#

你不能@Autowired一个静态字段,但是有一个技巧可以处理这个问题:

@Component
public class StatisticLogger {

  private static Dao dao;

  @Autowired
  private Dao dao0;

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

}

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

x9ybnkn6

x9ybnkn62#

经典的自动装配可能不起作用,因为静态类不是Bean,因此不能由Spring管理。有一些方法可以解决这个问题,例如在XML中使用factory-method方法,或者在静态初始化器块中从Spring上下文加载Bean,但我建议您更改设计:
不要使用静态方法,使用你需要的服务。如果你使用Spring,你最好正确地使用它。依赖注入是一种面向对象的技术,只有当你真正接受OOP时它才有意义。

q8l4jmvw

q8l4jmvw3#

我知道这是一个老问题,但只是想分享我做了什么,由@Weibo Li的解决方案是好的,但它提出的问题声纳临界警报有关分配非静态变量到静态变量
我解决它的方法没有声纳警报如下
1.我将StatisticLogger更改为singlton类(不再是静态的),如下所示

public class StatisticLogger {
private static StatisticLogger instance = null;
private Dao dao;

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);
}
}

1.我创建了一个服务(或组件),它可以自动连接我想要的服务,并在singlton类中设置它。这是安全的,因为在Spring中,它会在执行其他操作之前初始化所有托管bean,这意味着在任何操作可以访问StatisticLogger之前,都会调用下面的PostConstruct方法,类似于以下内容

@Component
public class DaoSetterService {

@Autowired
private Dao dao0;

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

}

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

9cbw7uwe

9cbw7uwe4#

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

public static void AddLoginEvent(LogStatisticBean user, DAO dao){
    dao.callMethod();
}
i2byvkas

i2byvkas5#

现在回答这个问题可能为时已晚,特别是当一个问题已经有了一个公认的答案时,但如果其他人面临同样的问题,这可能会有所帮助。
StatisticLogger类中创建Dao服务的示例。

public static Dao daoService = new Dao();

然后,通过StatisticLogger类的构造函数自动连接服务示例。

@Autowired
public functionName(Dao daoService0) {
    this.daoService = daoService0;
}

//use this service as usual in static class
daoService.fun();

我认为这是解决这个问题最简单的办法。

相关问题