spring-装配注解
1. @Autowird
1. 作用
实现依赖注入,spring容器会对bean中所有字段、方法进行遍历,标注有@Autowired注解的,都会进行注入。
2. 定义
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { /** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */ boolean required() default true; }
可以用在构造器、方法、方法参数、字段、注解上。
参数:
required:标注的对象是否必须注入,可能这个对象在容器中不存在,如果为true的时候,找不到匹配的候选者就会报错,为false的时候,找不到也没关系 。
处理 @Autowird 的类:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
3. 查找候选者的过程
@Autowired标注在字段上面:假定字段类型为一个自定义的普通的类型,候选者查找过程如下:
@Autowired标注在方法上或者方法参数上面:假定参数类型为为一个自定义的普通的类型,候选者查找过程如下:
上图中深色的表示方法注入和字段注入查找过程的不同点。
上图中展示的是方法中只有一个参数的情况,如果有多个参数,就重复上面的过程,直到找到所有需要注入的参数。
总结:按类型找->通过限定符@Qualifier过滤->@Primary->@Priority->根据名称找(字段名称或者方法名称)
4. 注入到 collection 或者 map
1. 注入到 collection
@Autowired private List<AnimalService> list;
会将所有 AnimalService 类型的 bean 注入到 list,可以通过 @Qualifier 过滤,只注入需要的 bean。@Primary 不会过滤。
2. 注入到 Map
@Autowired @Qualifier private Map<String, AnimalService> map;
将所欲 AnimalService 类型的 bean 注入 map,作为 value,而对应的 key 是 bean 的名字。同样可以使用 @Qualifier 过滤。
5. 注入方式
通过源码,@Autowired 的作用域可以看到 @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
,是可以用在这些上面的。
先随便定义一个 bean,用来做被注入的对象。
@Component public class Dog { public void run(){ System.out.println("狗子跑啊"); } }
1,属性注入
@Service public class FieldService { @Autowired private Dog dog; public void test(){ dog.run(); } }
对属性做注入
优点:
- 实现简单,使用简单
缺点:
- 无法注入 final 变量
- 循环依赖问题,由于 spring 使用三级循环解决了 set 方法注入时的循环依赖问题,因此如果存在单例的循环依赖也是可以通过编译的,但是实际上我们要尽量避免循环依赖问题。
2,set 方法注入
@Component public class SetterService { private Dog dog; @Autowired public void setDog(Dog dog) { this.dog = dog; } public void test(){ dog.run(); } }
setter注入是指将一个类的依赖通过设置一个公共的setter方法注入到该类中,这样就能够让该类使用这个依赖。setter方法通常在类中定义为public,并且以set开头,接着是一个单词,表示注入的属性的名称。
方法注入:如果方法中有实体参数,会对方法里面的参数进行装配
优点
- 完全符合单一职责的设计原则,因为每个Setter只针对一个对象。
缺点
- 和属性注入一样,无法注入 final 属性
- 注入对象可能被更改,setter 方法,可能随时被调用。
3,构造器注入
@Component public class ConstructService { private Dog dog; @Autowired public ConstructService(Dog dog){ this.dog = dog; } public void test(){ dog.run(); } }
构造方法注入是Spring官方从4.x之后推荐的注入方式,如果构造方法只有一个,那么 @Autowired 不是必须的,会对构造器的参数进行注入。
优点
- 可注入 final 属性,由于构造方法只会在对象创建的时候执行一次,避免了像Setter注入那样,不存在注入对象被随时(调用)修改的情况。
- 注入对象被完全初始化
缺点
- 循环依赖问题无法解决,其实我们应该尽量避免循环依赖问题,从这方面看这不能算个缺点。
2. @Resource
1. 作用
和@Autowired注解类似,也是用来注入依赖的对象的,spring容器会对bean中所有字段、方法进行遍历,标注有@Resource注解的,都会进行注入。
2. 定义
javax.annotation.Resource @Target({TYPE, FIELD, METHOD}) @Retention(RUNTIME) public @interface Resource { String name() default ""; ..其他不常用的参数省略 }
这个注解是javax中定义的,并不是spring中定义的注解。
从定义上可以见,这个注解可以用在任何类型上面、字段、方法上面。
注意点:
用在方法上的时候,方法参数只能有一个。
处理 @Resource 源码:org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
3. 查找候选者过程
先按Resource的name值作为bean名称找->按名称(字段名称、方法名称、set属性名称)找->按类型找->通过限定符@Qualifier过滤->@Primary->@Priority->根据名称找(字段名称或者方法参数名称)
将相当于在 @Autowired 前面加了通过 bean 名称查找,找不到就按 @Autowired 来
3. @Qualifier
1. 限定符
这个单词的意思是:限定符。
可以在依赖注入查找候选者的过程中对候选者进行过滤。
2. 定义
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Qualifier { //标记名称 String value() default ""; }
由于使用了 @Inherited 注解,所以 @Qualifier 注解会被子类继承
3. 实例
@Component @Qualifier("subLevel") public class ProgressPaymentJDKServiceImpl implements ProgressPaymentLevelService {} @Component @Qualifier("subLevel") public class ProgressPaymentFBDWServiceImpl implements ProgressPaymentLevelService {} @Component @Qualifier("subLevel") public class ProgressPaymentDWGCServiceImpl implements ProgressPaymentLevelService {} @Component public class ProgressPaymentBDServiceImpl implements ProgressPaymentLevelService {}
@Autowired @Qualifier("subLevel") private List<ProgressPaymentLevelService> progressPaymentLevelServiceList; @Autowired private List<ProgressPaymentLevelService> progressPaymentLevelServiceList1;
4. @Primary
1. 作用
注入依赖的过程中,当有多个候选者的时候,可以指定哪个候选者为主要的候选者。
2. 定义
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Primary { }
本文作者:Hi.PrimaryC
本文链接:https://www.cnblogs.com/cnff/p/17653348.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步