这是一个带有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无法在静态对象上工作,因为它们是为早期创建的,所以还没有创建自动维护机制。
答案 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警告
我解决它没有声纳警报的方式如下
我将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);
}
}
我创建了一个服务(或组件),它自动装配我想要的服务并在singlton类中设置它 这是安全的,因为在Spring中它将在执行任何其他操作之前初始化所有托管bean,这意味着在任何可以访问StatisticLogger之前始终调用下面的PostConstruct方法 像这样的东西
@Component 公共类DaoSetterService {
@Autowired
private Dao dao0;
@PostConstruct
private void setDaoValue () {
StatisticLogger.getInstance().setDao(dao0);
}
}
我没有将StatisticLogger用作静态类,而只是将其用作StatisticLogger.getInstance(),我可以访问其中的所有方法
答案 3 :(得分:0)
您可以将DAO从调用它的地方传递给StatisticLogger
。
public static void AddLoginEvent(LogStatisticBean user, DAO dao){
dao.callMethod();
}