@Autowired注解在抽象类中失效的原因及解决
作者:jy的blog 发布时间:2021-07-15 06:12:04
@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.print(dao.toString());
}
}
在我们实例化子类对象的时候,抽象父类不能实例化,因为spring注入的是实例对象,而不是类,所以spring不会将dao自动装配注入到一个实例中。但是我们通过在在抽象类中获取的上下文对象中却可以拿到dao,因为这个上下文对象
是我们自己手动new出来的,不是spring通过反射注入到对象中去的。因此这种方案是可行的。
下面介绍一种更优雅的解决方案:
1.同样是定义一个抽象类
public class BaseService {
Dao dao;
}
2.在子类中使用注解
@Component
public class myService extends BaseService{
//Autowired修饰方法时,根据方法参数类型判断实例化哪个类
@Autowired
public void printDao(Dao dao){
super.dao = dao;//父类属性注入
}
public void print(){
System.out.print(dao.toString());
}
}
这样写是不是要比我们直接去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_,并解释了一些关键点。
来源:https://www.cnblogs.com/jy107600/p/7490390.html
猜你喜欢
- List接口介绍—ArrayList有序、可重复线程不安全,因为没有synchronized修饰ArrayList源码结论ArrayList
- 最近做项目,ORM 使用的是 MyBatis,为了偷懒,我自然而然的想到了使用 MyBatis Generator(MBG)来生成数据库表对
- 介绍什么是ThreadLocal?ThreadLocal叫做线程变量,用于在多线程环境下创建线程本地变量。通俗的讲,ThreadLocal可
- 最近正式入坑Flutter,首先从环境搭建开始,看了网上好多关于Windows环境搭建的资料,基本都是按官方文档写的,看完的感受是,还不如直
- 开发环境使用jdk1.8.0_60,把springboot 项目打成war包后,部署到apache-tomcat-7.0.68时报错如下,换
- Spring Cloud feign GET请求无法用实体传参代码如下:@FeignClient(name = "eureka-c
- Controller @RequestMapping作用@RequestMapping是一个用来处理请求地址映射的注解,可用于类或者方法上。
- JSON.toJSONString()空字段不忽略修改使用JSON.toJSONString(object)方法,返回的json中,默认会将
- Mybatis基础回顾与高级应用数据库:mysql5.7jdk:15引入依赖<!--引入依赖--> &
- 最近在做一个项目,遇到了项目打成 war 包的一个问题,项目创建时选择的时 jar 包方式,后因项目部署要求,需要打成 war 包部署,遇到
- 解决办法:1.VCS--->Enable Version Control Integration2.选择要关联的版本工具补充:git
- SpringMVC @RequestBody自动转json Http415错误项目中想用@RequestBody直接接收json串转成对象网
- 在为什么阿里巴巴不建议在for循环中使用”+”进行字符串拼接一文中,我们介绍了几种Java中字符串拼接的方式,以及优缺点。其中还有一个重要的
- 1:Maven命令下载源码和javadocs当在IDE中使用Maven时如果想要看引用的jar包中类的源码和javadoc需要通过maven
- 目录ShutdownHook介绍ShutdownHook原理ShutdownHook的数据结构与执行顺序ShutdownHook触发点Shu
- 1. Spring Boot Condition功能与作用@Conditional是基于条件的自动化配置注解, 由Spring 4框架推出的
- 目录一、基础配置1、<parent> 标签1)使用 spring-boot-starter-parent2)使用自定义 pare
- java 设计模式之单例模式前言:在软件开发过程中常会有一些对象我们只需要一个,如:线程池(threadpool)、缓存(cac
- Spring boot + Spring data jpa + Thymeleaf批量插入 + POI读取 + 文件上传pom.xml:&l
- 前言最近写了一篇博客是关于 使用Jenkins来构建SVN+Maven项目 ,这里使用的的代码版本工具是SVN,但是事实上也有很多公司使用G