- 什么是自动装配?
- 自动装配就是为我们的类类型属性自动赋值,就是我们之前需要用ref引入外部的那些属性,自动装配则帮助我们自动完成了这个操作
场景模拟
- 在三层结构中,常常会有view层的controller调用service层的业务方法,service层的业务方法调用数据访问层dao的sql语句
- 假设我的有一个userController,userService,userDao
- userController接收到了我的请求,调用userService中的方法,userService的方法需要调用userDao中的语句
- 那么我在userController这个类中需要有一个成员变量userService,这样使用userService.方法()调用,userService中调用userDao也需要userDao成员变量来调用相关的方法
- 我不使用new一个对象的方式去为它们赋值,而是为它们设定好set方法进行注入
- 配置文件写法
<bean id="usercontroller" class="com.cn.zt.mvc.controller.impl.UserControllerImpl">
<property name="userService" ref="userservice"/>
</bean>
<bean id="userservice" class="com.cn.zt.mvc.service.impl.UserServiceImpl">
<property name="userDao" ref="userdao"/>
</bean>
<bean id="userdao" class="com.cn.zt.mvc.dao.impl.UserDaoImpl"/>
基于xml使用自动装配
- 根据指定的策略,在IOC容器中匹配某个bean,自动为bean中的类类型的属性或者接口类型的属性赋值
- 使用自动装配之后,就不需要再bean标签中使用property标签来为类类型属性赋值了
- 我们可以通过bean标签中autowire来实现自动装配
<bean id="usercontroller" class="com.cn.zt.mvc.controller.impl.UserControllerImpl" autowire="">
- autowire属性中有5个可选项
- no和default:都表示不装配,即bean中的属性不会自动匹配某个bean为属性赋值,此时属性为默认值
- 这个默认值就是你手动用property标签注入,如果没写,那就是空
- byType:根据要赋值的属性的类型,在IOC容器中匹配某个bean,为属性赋值
- 比如,我userController的bean,我有个接口类型属性userService,在bean标签中我配置了这个接口类型属性的实现类userServiceImpl,那么自动装配就会将我这个实现类的bean注入到userController的userService属性中。
<bean id="usercontroller" class="com.cn.zt.mvc.controller.impl.UserControllerImpl" autowire="byType">
- 注意
- 在类型匹配自动装配中,没有找到一个bean,就会使用默认值
- 如果找多个bean匹配,报错,报NoUniquebean的错,所以要求只能有一个bean匹配
- byName:它会将我们属性的属性名当做要匹配的bean的id来自动匹配
- 我还是提醒一下,属性名的概念和成员变量有区别,切记,属性名时set方法后面跟的名字并且第一个字母小写
- 用byName,就算id能匹配上,也要求你属性的类型能够匹配,不然使用默认值
- no和default:都表示不装配,即bean中的属性不会自动匹配某个bean为属性赋值,此时属性为默认值
- 用xml自动装配是比较少用的,因为xml中的自动装配是在bean标签中,这样会使得你的这个类的所有属性都会自动装配,而我们有些属性是想自己赋值的
基于注解来管理bean以及自动装配
基于注解的管理bean
- 基于注解管理bean也有缺点,比如你不能管理依赖包中的类,只能通过xml文件来
- 注解与扫描基本使用
- 注解:是一种标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作
- 常用注解
- @Component:将类标识为普通组件
- @Controller:将类标识为控制层组件
- @Service:将类标识为业务层组件
- @Repository:将类标识为持久层组件
- 这里的组件就是指一个个bean
- 其他三个组件都是由Component扩展而来,方便开发人员分辨各个层面,它们拥有不同的处理机制。但对于ioc容器来说,实质上没有太大区别。
- 常用注解
- 扫描:spring为了知道程序员在哪里标记了什么注解,就需要通过扫描的方式,来进行检测,然后根据注解进行后续操作
- 在spring配置文件中配置相关的扫描标签,配置扫描才能检测注解
<context:component-scan base-package="com.cn.zt.mvc"></context:component-scan>
- 这个context:component-scan标签就是一个扫描标签,它的属性base-package的值表示扫描的包的范围
- 注解:是一种标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作
- 扫描组件的详细配置
- 由于我们以后的spring和spring mvc 有各自扫描的范围,如果spring和spring mvc都扫描了同一个范围,一个组件会被扫描多次,那么这个组件会同时被这两个框架所影响
- 在context:component-scan标签有两个子标签
<context:exclude-filter type="" expression=""/>
,这个表示排除扫描什么- type属性有两个常用的值,表示排除扫描的方式
- annotation:表示根据注解来排除
- 它对应的expression属性的值填一个注解的全类名,比如Controller注解的全类名
org.springframework.stereotype.Controller
我写了这个,那么Controller注解将不会被扫描 - 这种排除方式就是注解排除,排除所有该注解的组件
- assignable:表示根据类型来排除
- 它对应的expression属性值往往填一个具体的全类名,表示个这个类不被扫描
- 这种方式是类型排除,排除这个类的组件
- type属性有两个常用的值,表示排除扫描的方式
<context:include-filter type="" expression=""/>
,这个表示只扫描什么- 如果想使用这个子标签,它的父标签一定要改变父标签use-default-fiters的属性值为false,不然它默认是true把包扫描一遍,这个标签不起作用
- 它的type属性有两种 包含扫描 方式,注解包含,类型包含。
- 跟上面一样的用法,只不过,它是包含而已,就是只扫描它指定的
- 常用的还是排除扫描,不用设置use-default-fiters属性,而且用的多
- 通过注解加扫描添加到ioc中的bean的id
- 默认的bean的id就是类的小驼峰,比如我UserController的注解是Controller,它的bean的id是userController,它的首字母会小写,你原先的类名如果是usercontroller,它的bean的id就是usercontroller
- 自定义bean的id在注解中设置
@Controller("usercontroller")
这样它的bean的id就会被设置为括号里名字,也就是修改注解的value,但是我们常用的还是类型获取bean,id用的少
- 基于注解的自动装配
- 自动装配注解的使用
@Autowired
- 它的标识位置
- 成员变量上,Spring 会自动将匹配的依赖注入到该变量中(常用)
- set方法上,被标记的方法会在对象创建后注入相应依赖
- 有参构造上,Spring 会在创建对象时,通过构造方法注入所需的依赖
- 它的标识位置
- 注解
@Autowired
自动装配的原理- 它是默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
- 如果我的注解已经被扫描,在ioc中有对应类型的bean,我又在配置文件中配置了一个bean标签对应类型也是它,就会有多个类型匹配的bean了,自动装配默认的是byType,那么它会自动变成byName匹配
- 如果byType和byName的方式都无法实现自动装配,如果ioc容器中有多个类型匹配的bean,且这些bean的id和要赋值的属性的属性名都不一致,就会报NoUnique的错
- 这种的话可以使用注解
@Qualifier(value)
,通过这个注解的value值来指定一个bean的id来将这个bean为这个属性赋值
- 这种的话可以使用注解
- 如果我byType方式没有找到类型匹配的bean,xml配置文件的byType的这种情况和注解的这种情况还是有区别的,注解的byType方式没找到类型匹配的bean,它会报一个spring的错,因为注解@Autowired要求一定自动装配,你要设置它的一个属性
@Autowired(required = false)
,这样它就会能装配装配,不能就为空- 报错了反正三个方面,注解加扫描加自动装配,看这几个有没有问题
- 自动装配注解的使用