在Spring的依赖注入可以使用构造函数注入,也可以使用注解实现依赖注入,那么如何使用注解实现自动装配呢?
1.导入约束:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd"
2.配置注解的支持:易忘
代码示例:
用法: 这个注解我们需要加在需要进行自动装配的属性/属性的set方法上
好处:我们可以不写需要自动装配的属性的set方法
使用前提:这个属性在IOC容器中已经注册好了,且注册在容器中的bean满足byName的使用条件或byType的使用条件(必须有set方法存在),使用的时候它会先使用byType进行自动装配,byType失败就使用byName进行自动装配
代码示例:
实体类:
package com.lyc.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class People {
@Autowired
private Dog dog;
@Autowired
private Cat cat;
private String name;
public Dog getDog() {
return dog;
}
// public void setDog(Dog dog) {
// this.dog = dog;
// }
public Cat getCat() {
return cat;
}
// public void setCat(Cat cat) {
// this.cat = cat;
// }
public String getName() {
return name;
}
@Override
public String toString() {
return "People{" +
"dog=" + dog +
", cat=" + cat +
", name='" + name + '\'' +
'}';
}
}
public class Cat {
public void shout(){
System.out.println("miao~");
}
}
public class Dog {
public void shout(){
System.out.println("wang~");
}
}
bean.xml
测试类:
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people", People.class);
people.getDog().shout();
people.getCat().shout();
}
运行效果:
让我们进入@Autowired的源码中探究一下
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
我们可以看到@Autowired中还有一个默认的布尔值方法,经过测试得出
如果显示定义了Autowired的request属性为false,则表示该属性可以为null,否则不允许为空
让我们在探究一下,为空?这让我想到了@Nullable,经过测试,和'request = false'效果一致
注解@Qualifier是配合@Autowired 一起/配套 使用的,它的使用场景就是当注解@Autowired的使用条件都不满足的时候,即容器中这个对象属性的时候既不满足byName自动装配的使用条件,又不满足byType自动装配的使用条件,此时,我们就可以通过@Qualifier注解,按照byName显式的为这个对象属性指定一个bean, 这样容器就知道怎么自动装配person bean了
拓展:
byname:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id
bytype:会自动在容器上下文中查找,和自己对象属性类型相同的bean id
弊端:必须保证这个类型全局唯一,才能运行
案例代码:
其他类不变,主要变化在bean类与实体类
bean.xml
实体类:
@Autowired
@Qualifier(value = "dog111")
private Dog dog;
@Autowired
@Qualifier(value = "cat111")
private Cat cat;
private String name;
测试类
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
People people = context.getBean("people", People.class);
people.getDog().shout();
people.getCat().shout();
}
测试结果:
@Resource的作用 = @Autowired+@Qualifier,但是开发中最常用的还是@Autowired注解
首先,这个注解在javax.annotation.Resource包中,但是JDK11以后完全移除了javax扩展,所以不能直接使用@resource注解
解决办法:通过maven引入依赖
简单示例:
public class People {
//如果显示定义了Autowired的request属性为false,则表示该属性可以为null,否则不允许为空
@Resource(name = "dog111")
private Dog dog;
@Resource(name = "cat111")
private Cat cat;
private String name;
@Autowired:自动装配,先通过type,再使用name,都不行就报错[常用]
@Qualifier:配合@Autowired使用,当@Autowired报错时,使用@Qualifier(value=“指定bean的ID值”)
@Resource:Java自己的注解,使用的使用如果JDK>=11,可以使用maven依赖导入javax包,否则这个注解使用不了
@Resource先通过name,再使用type自动装配,都不行就报错
可以通过@Resource(name = “XXX”)实现和@Qualifier相同的效果
@Nullable和@Autowired(required = false)效果相同,可以使得对象属性为NULL也不报错
Spring的依赖注入为什么推荐使用构造函数注入而不推荐使用@Autowired?
答:
在官网中讲到,Spring团队中通常提倡构造函数注入,因为构造函数注入允许将应用程序组件变为不可变对象,并确保所需的依赖项不为null,此外,构造函数注入的组件始终以完全初始化状态返回给客户端(调用)代码
被@Autowired修饰后,你就不能把该属性设为不可变量,即不能加上final关键字, 而构造函数可以,因为有时候我们确实需要将项目中的属性设为不可变量
而有时候我们可能会有多个构造函数,那这种情况,spring就会不知道选择哪个构造函数作为Bean,这一点,在官网中也有说到:顺便说,大量的构造函数参数是一种糟糕的代码设计,这意味着这类可能具有太多责任,应该重构以更好地解决适当的关注点分离问题
所以,这意味着我们的类最好是单一职责。
希望对大家有所帮助