1.属性赋值
1.1 @Value
使用@Value注解赋值;
- 基本数值
- 可以写Spring的EL表达式; #{}
- 可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
1.2 @PropertySource
使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;
加载完外部的配置文件以后使用${}取出配置文件的值
@PropertySource(value={“classpath:/person.properties”}) 数组类型,可以支持一次性引入多个文件。
- 另外@PropertySource 是一个可重复的注解,可以使用@PropertySources注解引入多个@PropertySource标注的properties配置文件
1 | ({ElementType.TYPE}) |
测试代码如下:
1 | //实体类信息 |
测试结果:
1 | Person{name='张三', age=18, nickName='小李四'} |
2.自动装配
自动装配;
Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
2.1 @Autowired、@Qualifier、@Primary
2.1.1 @Autowired
2.1.1.1 概念性总结
概念:Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。
原理:其实在启动spring IOC容器时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。
注意事项:
- 1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
- 2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查 applicationContext.getBean(“bookDao”)所以容器中有多个相同组件时,名称不应该乱起。
- 3)、自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false);默认required=true
2.1.1.2 默认注入情况测试
默认注入情况:名字默认是类名首字母小写
1 | //service 层代码,自动注入dao层 |
测试结果:通过上文注意事项可知,Spring容器注入时会先通过类型找到两个BookDao类型的对象,第二次会通过 默认是类名首字母小写在查找一次。故Service层注入的BookDao对象应该为nameFlag = “1”; 的对象
1 | 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4aa8f0b4: startup date [Sat Dec 15 18:56:29 CST 2018]; root of context hierarchy |
如果此时修改测试类使用IOC容器按类型获取BookDao此时,因为容器中有两个BookDao类型的对象,当打印时就会报错。
1 |
|
2.1.1.3 @Autowired(required=false)
自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false);
1 | ({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) |
测试用例
1 | //业务层代码,自动注入Dao层对象,required = false |
2.1.1.4 @Autowired:构造器,参数,方法,属性
@Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
默认情况说明:
- @Bean标注的方法创建对象的时候,方法参数的值从容器中获取
- 默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
@Autowired标注说明:
- 1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配
- 2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取.
- 3)、放在参数位置:
2.1.2 @Qualifier
@Qualifier(“XXX”) Spring的Bean注入配置注解,该注解指定注入的Bean的名称,Spring框架使用byName方式寻找合格的bean,这样就消除了byType方式产生的歧义。
@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名。@Qualifier需要和 @Autowired一起使用。
1 | public class BookService { |
2.1.3 @Primary
@Primary:让Spring进行自动装配的时候,默认使用首选的bean;也可以继续使用@Qualifier指定需要装配的bean的名字。
通过下面的示例也可以看出@Primary和@Qualifier 在一定程度上有所冲突,如果我们service层代码使用@Qualifier指定注入名称,即使在相同类型的其他Bean 上标注@Primary,Spring注入Service层的也是根据@Qualifier标注注入的。
1 |
|
测试结果:可以看出Spring容器加载了两个BookDao类型的bean,向Serveice层注入的是 @Qualifier(value = “bookDao”)标注的。
1 | com.rocklei123.config.MainConfigOfAutowired$$EnhancerBySpringCGLIB$$7d34398f@37e547da |
2.2 @Resource(JSR250)和@Inject(JSR330)
Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
2.2.1 @Resource:
- 可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
- 没有能支持@Primary功能
- 没有支持@Autowired(reqiured=false);
1 |
|
2.2.2 @Inject:
@Inject支持构造函数、方法和字段注解,也可能使用于静态实例成员。可注解成员可以是任意修饰符(private,package-private,protected,public)。注入顺序:构造函数、字段,然后是方法。父类的字段和方法注入优先于子类的字段和方法,同一类中的字段和方法是没有顺序的。
- 需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;但是支持@Primary
1 | <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject --> |
2.3 @Autowired 和 @Resource、@Inject 的区别
相同点
- @Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理依赖注入。但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。当然,两者都是BeanPostProcessor。
- 三个注解都能实现自动装配功能
不同点
注解定义不同
@Autowired:Spring定义的,脱离Spring框架就没有了;
@Resource、@Inject都是java规范,其他IOC框架也会支持。
默认注入方式不同
- @Autowired和@Inject: 默认 autowired by type,可以通过@Qualifier 显式指定;
- @Resource:默认 autowired by field name,如果 autowired by field name失败,会退化为 autowired by type;可以 通过@Qualifier 显式指定 autowired by qualifier name;如果 autowired by qualifier name失败,会退化为 autowired by field name。
功能性差异
- @Resource 没有能支持@Primary功能;没有支持@Autowired(reqiured=false)功能;
- @Inject 虽然支持@Primary功能功能,但是不支持@Autowired(reqiured=false)功能;
- @Autowired支持@Primary功能,@Autowired(reqiured=false)功能;
2.4 自定义组件注入Spring容器底层的一些组件
2.4.1 xxxAware介绍
自定义组件实现xxxAware接口,在创建对象的时候,会调用接口规定的方法注入相关组件;xxxxAware接口把Spring底层一些组件注入到自定义的Bean中;
测试代码:
1 | package com.rocklei123.bean; |
2.4.2 xxxAware底层原理
xxxAware原理:功能使用xxxProcessor,通过后置处理器功能实现;
如: ApplicationContextAware==》ApplicationContextAwareProcessor;
以ApplicationContextAwareProcessor为例源码:
1 | package org.springframework.context.support; |