注解
和XML配置文件一样,注解本身并不能执行,注解本身只是做一个标记,具体功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能执行具体操作
本质上:所有的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行
标记
在使用注解标记时,我们要在 需要被IOC容器管理的类上 加上注解
常用注解:
@Component:将类标识为普通组件
@Controller:将类标识为控制层组件
@Service:将类标识为业务层组件
@Repository:将类标识为持久层组件
注:
1.这四个注解的作用是完全一样的,下面三个注解都是在第一个注解的基础上起了三个新的名字
但是为了代码的可读性,我们仍然要根据对应的关系来进行注解
2.这四个注解应该标记在要被管理的类上,不能被标记在接口上
扫描组件
在使用主键标记了需要被管理的类后,我们还需要扫描这些类,判断是否使用了注解
基础的扫描方式
在IOC容器中使用context:component-scan来设置我们需要扫描的包(需要context约束)
<context:component-scan base-package="com.controller"></context:component-scan>
若我们有多个要扫描的包,可以直接使用逗号分隔
<context:component-scan
base-package="com.controller,com.dao.impl,com.service">
</context:component-scan>
也可以直接扫描一个大包,将需要扫描的包都包括进去
<context:component-scan base-package="com"></context:component-scan>
注:我们选择的包的范围越大,扫描到没有注解的类或接口就越多,导致效率降低,因此包的范围越小,越精确,效率就越高
指定要排除的组件
我们在进行扫描时,可能会出现某些类不想要让这个IOC容器管理的情况,那么此时就需要排除这些类
context:component-scan有子标签
context:exclude-filter:指定排除规则,其有属性
type和expression
type="annotation",根据注解排除,expression中设置要排除的注解的全类名
type="assignable",根据类型排除,expression中设置要排除的类型的全类名
<context:component-scan base-package="com.atguigu">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<!--<context:exclude-filter type="assignable"
expression="com.atguigu.controller.UserController"/>-->
</context:component-scan>
仅扫描指定组件
为实现进扫描指定组件的功能,需要进行两步操作:
1.设置context:component-scan的属性 use-default-filters="false"
2.使用context:component-scan的子标签 context:include-filter ,然后设定type和expression来指定要扫描那些类
use-default-filters="true"(默认),所设置的包下所有的类都需要扫描,此时可以使用排除扫描
use-default-filters="false",所设置的包下所有的类都不需要扫描,此时可以使用包含扫描
<context:component-scan base-package="com.atguigu" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<!--<context:include-filter type="assignable"
expression="com.atguigu.controller.UserController"/>-->
</context:component-scan>
仅扫描使用的较少
注:一个扫描中可以设置多个排除或多个包含,但不能同时使用排除和包含
组件所对应的bean的id
默认id
在我们使用XML方式管理bean时,每个bean都有一个唯一标识,便于在其他地方引用。现在使用注解后,每个组件仍然应该有一个唯一标识
默认情况下,类名首字母小写就是bean的id
例:UserController类对应的bean的id就时userController
自定义id
除默认id外,我们也可以通过表示组件的注解的value属性设置自定义id
如图,此时UserController对应的bean的id就是controller
自动装配
在使用XML管理bean时,如果bean中的某个属性是一个类类型的属性,我们可以自动装配为其赋值
在注解管理bean中,要实现自动装配功能,我们可以使用@Autowired注解,该注解的标记位置有三种
1.在成员变量上使用@Autowired注解,此时不需要提供set方法
如图,为UserController类的userService成员变量实现自动装配,只需要在成员变量上使用注解即可
2.在成员变量的set方法上使用@Autowired注解
3.在为当前成员变量赋值的有参构造上使用@Autowired注解
注:一般使用第二种
@Autowire注解的原理
默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
若有多个类型匹配的bean,此时会使用byName的方式实现自动装配的效果,即将要赋值的属性的属性名作为bean的id去匹配bean并为其赋值
若IOC容器中有多个类型匹配的bean,且这些bean的id和要赋值的属性的属性名都不同,则会抛异常,此时可以在要赋值的属性上添加一个@Qualifier注解,通过该注解的value属性值,指定某个bean的id,用这个bean为属性赋值
注:若IOC容器中没有任何一个类型匹配的bean,会抛出异常
在@Autowired注解中有个属性required,默认值为true,表示必须完成自动装配
可以将其设置为false,此时若无法装配则会使用默认值