课程信息
- 学习课程:Java工程师2022版
- 章节名称:Spring Ioc容器与Bean管理-使用注解方式实现Spring Ioc
- 讲师:悟空
课程内容
通过XML、注解或者Java Config配置IoC容器本质是一样的
基于注解配置IoC容器
基于注解的优势:
摆脱繁琐的XML形式的bean与依赖注入配置
基于“声明式”的原则,更适合轻量级的现代企业应用
让代码可读性变得更好,研发人员拥有更好的开发体验
三类注解:
组件类型注解——声明当前类的功能与职责
自动装配注解——根据属性特征自动注入对象
元数据注解——更细化的辅助IoC容器管理对象的注解
四种组件类型注解(在将对象实例化之后还自动注入强化了这个类):
@Component:组件注解,通用注解,被该注解描述的类将被IoC容器管理并实例化
@Controller:语义注解,说明当前类是MVC应用中的控制器类
@Service:语义注解,说明当前类是Service业务服务类
@Repository:语义注解,说明当前类用于业务持久层,通常描述对应Dao类
<context:component-scan base-package=“com.imooc”>
<context:exclude-filter type=“regex” expression=“com.imooc.exl.*”/>
</context:component-scan>
基于注解初始化ioc容器
1.创建基于Spring基于注解的Schema和基于XML文件的不太一样(01:18)处找到具体复制位置
xmlns:context=“http://www.springframework.org/schema/context”
<context:component-scan base-package=“com.imooc”/>
组件类型注解默认beanId为类名首字母小写,也可以在注解后加括号重新命名beanId,一般都使用默认值!而且他们都是单例的,只有单例的会在IoC初始化的时候进行创建
//组件类型注解默认beanId为类名首字母小写userDao
@Repository(“uDao”)
public class UserDao{}
两类自动装配注解
按类型装配 @Autowired 按容器内对象类型动态注入属性,由Spring机构提供
@Inject 基于JSR-330标准,其他同@Autowired,但不支持required属性
按名称装配 @Named 与Inject配合使用,JSR-330规范,按属性名自动装配属性
@Resource 基于JSR-250规范,优先按名称,再按类型智能匹配
为了让IoC容器在运行过程中自动为某个属性注入数据
如果装配注解放在set方法上,则自动按类型/名称对set方法参数进行注入,
但是一般不会设置set方法
因为Spring Ioc容器会自动通过反射技术将属性private修饰符自动改为public,直接进行赋值,然后再改回private
它是在运行时动态完成的,不依赖于set方法
所以用注解开发做依赖注入一般不写set方法
/* 如果装配注解放在属性上,
* Spring IoC容器会自动通过反射技术将属性private修饰符自动改为public,
* 也就意味着从外侧可以直接对属性赋值,就直接进行赋值
* 不执行set方法*/
@Autowired private IUserDao udao ;
/* 如果装配注解放在set方法上,则自动按类型
*名称对set方法参数进行注入
*ioc容器会自动将容器中类型为UserDao的对象注入到set方法参数中
*执行set方法中的代码,完成属性的赋值
*/
@Autowired
public void setUdao(UserDao udao) {
System.out.println("setUdao:" + udao);
this.udao = udao;
}
@Autowired默认是根据类型进行自动装配的,但是当存在多个满足条件的 Bean 时,则会根据名称进行注入。
代码中声明为:private IUserDao userDao,项目中存在两个该类型的Bean,则会继续按照名称进行注入,会直接将UserDao对象注入,故程序可以正常运行。
课程中声明为private IUserDao uDao时,项目中存在两个IUserDao类型的Bean,且不存在名为uDao的bean故会注入失败,出现报错提示“No qualifying bean of type ‘com.imooc.spring.ioc.dao.IUserDao’ available:expected single matching bean but found 2: userDao,userOracleDao
@Autowired默认按照类型byType自动装配,@Resource默认按照名称byName自动装配。
1、@Resource设置name属性,则按name在IoC容器中将Bean注入
2、@Resource未设置name属性:
以属性名作为bean name在IoC容器中匹配Bean,如有匹配则注入
按属性名未匹配,则按类型进行匹配,同@Autowired,需加入@Primary解决类型冲突
使用建议:在使用@Resource对象时推荐设置name或保证属性名与bean名称一致
@Resource
@Resource注解输入J2EE,有两个属性:name和type,而Spring将@Resouce注解的name属性解析为bean的名称,type属性则被解析为bean的类型。@Resource默认按照名称进行装配,名称可以通过name属性进行指定.
@Autowired
@Autowired注解属于Spring,默认按照类型装配,默认情况下要求依赖对象必须存在
@Resource与@Autowired都可以用来装配bean,都可以写在字段或setter方法上。
@Resource默认按照名称进行装配,如果乜有指定name属性,注解写在字段上时,默认是取字段名作为名称进行查找。如果注解写在setter方法上则是默认取属性的名称进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的时,如果name属性一旦指定,就只会按照名称进行装配。
@Resource的装配顺序如下:
1)如果同时指定name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
2)如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
3)如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4)如果即没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
@Autowired允许null值,需要将equired属性设置为false.如:@Autowired(required=false)
@Autowired想用名称装配,需要结合@Qualifier注解进行使用。在@Autowire配合@Qualifier使用时,会按照@Qualifier注解添加的名称进行注入。如:@Autowired@Qualifier(“test”)就是按照test名称进行装配。从而解决@Service重名问题
元数据注解
@Primary 按类型装配时出现多个相同类型对象,拥有此注解对象优先被注入
@PostConstruct 描述方法,相当于XML中init-method配置的注解版本
@PreDestroy 描述方法,相当于XML中destroy-method配置的注解版本
@Scope 设置对象的scope属性
@Value 为属性注入静态数据
@Scope(“singleton”);@Scope(“prototype”);用来设置对象是单例模式还是多例模式,和xml中的bean scope完全相同 单例模式在ioc容器初始化之前初始化对象,以后通过getbean获取的对象也都是这一个对象;多例模式在ioc容器初始化后采用getbean的形式调用后才进行对象初始化,且每次的对象都不同
@PostConstruct //与XML中的init-method作用完全相同,每次对象创建时执行完构造方法都要同步执行此方法
在xml中配置加载配置文件:
<!-- 通知SpringIoc容器初始化加载属性文件 -->
<context:property-placeholder location="classpath:config.properties"/>
@Value(${metaData})
@Value("${配置文件里的属性名}")(放在成员属性上,用来定义配置文件(properties/yml文件)中的属性,然后通过调用成员属性来获取配置文件中的属性值(静态数据);(@Value(“配置文件里的属性名”)然后通过调用成员属性来获取配置文件里的属性名))
学习收获
学习了使用注解实现Spring Ioc,常用的组件注解,自动装配注解,元数据注解,组件注解的区别和使用方式,自动装配注解放在属性上和set方法上的区别,以及自动装配注解@Autowired和@Resource的区别,常用的元数据注解用途和使用