@Autowired注解在抽象类中失效的原因及解决
@Autowired注解在抽象类中失效
最近在⼯作中遇到这个问题,在抽象类中使⽤Autowired这个注解,注⼊mybatis的dao时,总是出现空指针异常,通过⽇志的打印,发现是这个dao注⼊失败为空。然后通过new出spring上下⽂对象,再去调⽤getBean()⽅法,获取到这个注⼊的dao,这样是可⾏的,但是总是觉得这不是最佳实践,⼀定有⽐这个更加优雅的⽅式能解决这个问题。
我们来还原⼀下这个问题:
1.定义⼀个抽象类
声明为spring组件,在其中⾃动装配另⼀个bean:
@Component
public abstract class BaseService {
@Autowired
Dao dao;
}
2.然后在他的⼦类中使⽤这个⾃动装配的对象
@Component
public class myService extends BaseService{
public void print(){
//运⾏时为null
System.out.String());
}
}
在我们实例化⼦类对象的时候,抽象⽗类不能实例化,因为spring注⼊的是实例对象,⽽不是类,所
以spring不会将dao⾃动装配注⼊到⼀个实例中。但是我们通过在在抽象类中获取的上下⽂对象中却可以拿到dao,因为这个上下⽂对象
是我们⾃⼰⼿动new出来的,不是spring通过反射注⼊到对象中去的。因此这种⽅案是可⾏的。
下⾯介绍⼀种更优雅的解决⽅案:
1.同样是定义⼀个抽象类
public class BaseService {
Dao dao;
}
spring ioc注解2.在⼦类中使⽤注解
@Component
public class myService extends BaseService{
//Autowired修饰⽅法时,根据⽅法参数类型判断实例化哪个类
@Autowired
public void printDao(Dao dao){
super.dao = dao;//⽗类属性注⼊
}
public void print(){
System.out.String());
}
}
这样写是不是要⽐我们直接去new applicationContext更加优雅呢?
在抽象类中使⽤@Autowired
1.简介
在本快速教程中,我们将说明如何在抽象类中使⽤ @Autowired ⾃动装配注解。
我们将 @Autowired 应⽤于 abstract 抽象类,并关注此时要考虑的重点。
2.Setter ⽅式注⼊
我们可以在设置⽅法上使⽤_@Autowired_:
public abstract class BallService {
private LogRepository logRepository;
@Autowired
public final void setLogRepository(LogRepository logRepository) {
this.logRepository = logRepository;
}
}
当我们使⽤_@Autowired_上setter⽅法,我们应该⽤final 关键字,这样⼦类便不能覆盖setter⽅法。否则,注解将⽆法正常运⾏。
3.构造函数注⼊
我们不能在抽象类的构造函数上使⽤_@Autowired_。
Spring 不会在抽象类的构造函数上解析 @Autowired 注解。⼦类应为 super 构造函数提供必要的参数。
相反,我们应该在⼦类的构造函数上使⽤_@Autowired_:
public abstract class BallService {
private RuleRepository ruleRepository;
public BallService(RuleRepository ruleRepository) {
this.ruleRepository = ruleRepository;
}
}
@Component
public class BasketballService extends BallService {
@Autowired
public BasketballService(RuleRepository ruleRepository) {
super(ruleRepository);
}
}
4.备忘单
让我们总结⼀些要记住的规则。
⾸先,抽象类不会进⾏组件扫描,因为没有具体的⼦类就⽆法实例化。
其次,在抽象类中可以进⾏setter注⼊,但是如果不对setter⽅法使⽤_final_关键字,因⽽存在⼀定误⽤的风险。如果⼦类覆盖setter ⽅法,则应⽤程序可能不能正常运⾏。
第三,由于 Spring 在抽象类中不⽀持构造函数注⼊,因此通常应该让具体的⼦类提供构造函数参数。这意味着我们需要在具体⼦类中依赖构造函数注⼊。
最后,将构造函数注⼊⽤于必需的依赖项,并将setter注⼊⽤于可选的依赖项是⼀个很好的经验法则。但是,正如我们可以从抽象类的⼀些细微差别中看到的那样,通常在这⾥构造函数注⼊更为有利。
因此,实际上我们可以说具体的⼦类控制着它的抽象⽗类如何获得其依赖项。 Spring 在装配⼦类时,会对其依赖进⾏注⼊。
5.结论
在本⽂中,我们练习了在抽象类中使⽤_@Autowired_,并解释了⼀些关键点。
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论