SpringBoot 中当注解@Component同时在abstract父类和子类上出现时,会是什么情况?
springboot中常通过@Component来进行Bean的申明,Spring支持Bean之间的继承关系。但当父类是abstract时,情况会有所不同,下面通过实践来验证。
- 首先定义了一个abstract父类 Person . 并赋予了一些初始属性
public abstract class Person {
/*
* 年龄
*/
public String age = "13";
public String name = "小王";
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 定义一个子类 Student来继承该父类。
@Component(value = "student")
public class Student extends Person{
private String id;
private String className;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
这个时候来看看具体的结果,发现生成的 Bean 是能继承abstract的属性的。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
// Object person = SpringUtil.getApplicationContext().getBean("person");
Object student = SpringUtil.getApplicationContext().getBean("student");
Object sex = SpringUtil.getApplicationContext().getBean("sex");
}
}
通过debugger可以看到生成的Bean能够继承Person的属性。(这里需要注意的是abstract类是不会实例化生成Bean的,所以就算在Person父类上加上Component注解也无效,因为虚类本身是无法实例化的,所以当然也不会生成Bean)
- 如果abstract父类本身通过@Autowired依赖了其他的Bean,则子类在生成Bean的时候也能注入相应的Bean.
首先先定义新增一个类Sex,并将其通过Autowired引入Person。
@Component(value = "sex")
public class Sex {
private String sexname = "男";
public String getSexname() {
return sexname;
}
public void setSexname(String sexname) {
this.sexname = sexname;
}
}
Person类中加入引用:
public abstract class Person {
private String age = "13";
private String name = "小王";
@Autowired
private Sex sex;
........... 省略
}
可以看到,生成的Bean能够继承父类中依赖的Bean,并且两个"Sex"相同(都是Sex@5470),说明是同一个Bean,因为默认是单例的。
- 如果Person中属性是静态时,子类生成Bean时是无法继承的,但是由于是静态引用,所以又是可以访问的。代码如下:
首先在Person中添加静态的变量 height,并初始化一个值 180cm:
public abstract class Person {
private String age = "13";
private String name = "小王";
static String height = "180cm";
public String getHeight() {
return height;
} .......
}
- 当abstract中静态属性是具体的Bean时,情况如何?
将Person中的Sex属性改成静态的,由于是静态属性,无法直接通过@Autowired注入,需要通过set方式或者使用@PostConstruct注解注入,不知道的小伙伴自行百度。
public abstract class Person {
private String age = "13";
private String name = "小王";
static String height = "180cm";
public String getHeight() {
return height;
}
static Sex sex;
@Autowired
public void setSex(Sex sex){
this.sex = sex;
}
..................
}
和第四点的结论一致,无论是常用的属性或是具体的对象,静态的属性都无法继承,但是由于是“静态引用“,所以又能通过父类继承的方法正常访问和引用。
另外,当父类和子类同时拥有相同的静态变量或者静态方法时,是不会相互影响的,具体推荐看这一篇:
子类是否可以继承父类的static变量和方法
结语:水平有限,有不正之处望指正。