基于注解(Annotation)的组件扫描
在Spring中,尽管使用xml配置文件可以实现Bean的装配工作,但如果项目中有很多bean需要装配,会导致xml文件非常臃肿,给后续的升级和维护工作带来麻烦。因此,Spring提供了对注解的支持。
我们可以通过xml中配置spring的自动扫描,扫描到某个包,在被扫描包以及子包中的bean类上面写上特定的注解,当spring容器初始化的时候回扫描我们指定的包,将有特定注解的类自动管理成spring的Bean对象,以及自动维护对象与对象之间的关系。
什么是组件扫描
指定一个包路径,spring会自动扫描该包以及其子包所有组件类,当发现组件类定义前有特定的注解标记时,就将该组件纳入Spring容器,等价于xml配置文件中的bean标签
指定扫描类路径
要使用spring自动扫描需要在导入4个spring基础包的同时增加一个spring-aop的包,因为此包对注解提供了支持。导包如下:
使用context:component-scan标签来指定自动扫描的包路径,这样容器再初始化的时候就会自动扫描base-package属性指定的包以及子包中是否有特定注解的需要spring管理的类。
<!--指定自动扫描的包路径-->
<comtext:component-scan base-package="com.ls.entity"/>
自动扫描的注解标记
- @component:可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件Bean,并且可以作用在任何层次。Spring中还提供@Component 的三个衍生注解:(功能目前来讲是一致的)。
- @Repository:用于持久层的注解。
- @Service:用于业务层的注解。
- @Controller:用于控制层的注解。
注意:这四个注解都是写在类上面的,后面三个注解是为了让标注类本身的用途清晰,目前功能上和第一个通用注解是一致的。Spring在后续版本会对其增强。
自动扫描组件的命名
当一个组件在扫描过程中被监测到时,会生成一个默认id值为小写开头类名,也可以在注解中指定id。如:@Component("user1")
//不指定id,默认为类名小写"user"
//@Component
//指定Spring容器管理此类对象的id
@Component("user1")
public class User {}
指定组件的作用域
注解方式也可以通过在类上面的注解@Scope 指定作用域。默认为singleton如果需要其它作用域,如原型模式 即可使用此注解指明:@Scope(“prototype”)
//指定组件的作用域为原型模式,即每次请求都造一个新的对象,默认为单例模式
@Scope("prototype")
public class User {}
指定初始化和销毁回调
通过注解的方式,写在特定的方法上也可以指明Bean对象的初始化和销毁的回调函数。
- @PostConstruct:写在方法上,指定此方法为初始化回调方法
- @PreDestroy:写在方法上,指定此方法为销毁的回调方法
//指定初始化的方法
@PostConstruct
public void initMethod() {
System.out.println("我是初始化方法");
}
//指定销毁之前执行的方法
@PreDestroy
public void destroyMethod() {
System.out.println("我是对象销毁之前执行的方法");
}
指定依赖注入关系
Bean对象被spring容器自动扫描到之后,会造相应对象,我们还需要指定bean对象依赖的内容。可以通过下面的注解,给bean的属性 注入值:
-
@value 注解:用于基本数据类型和字符串的值的注入,如给用户名注入值:
@value("lucy")
. -
@autowired 注解:用于自动注入bean类型的对象,默认是按照类型自动装配,因此符合条件的对象不能超过一个,否则容器将不知道使用哪个对象,会报错。此时我们还可以通过@qualifier(“依赖的bean的id”)注解指明使用哪个对象来自动装配。
-
@qualifier 注解:配合 @autowired 注解使用,用于指明使用哪个对象来自动装配。如,指明装配id为computer的bean时可以使用:
@Qualifier("computer")
-
@Resource 注解:我们发现如果使用@autowired注解当需要指明注入的bean的id时还需要使用@qualifier注解,比较麻烦。此时我们还可以使用 @Resource 注解。@Resource注解单独使用时和@autowired效果一样,但是当需要指明注入的id时可以直接通过其name属性来指定,如,指明装配id为computer的bean时可以使用:
@Resource(name=”computer”)
。 此时,@Resource注解相当于@autowired+@qualifier。
接下来我们通过一个案例,看一下效果。
- Computer
@Data
@Component
public class Computer {
@Value("2")
private Integer id;
@Value("黑色")
private String color;
@Value("联想")
private String brand;
}
- User
@Data
//不指定id,默认为类名小写"user"
//@Component
//指定Spring容器管理此类对象的id
@Component("user1")
//指定组件的作用域为原型模式,即每次请求都造一个新的对象,默认为单例模式
@Scope("prototype")
public class User {
@Value("18")
private Integer age;
@Value("lucy")
private String username;
@Autowired
//指明装配id为computer的bean
@Qualifier("computer")
private Computer computer;
//指定初始化的方法
@PostConstruct
public void initMethod() {
System.out.println("我是初始化方法");
}
//指定销毁之前执行的方法
@PreDestroy
public void destroyMethod() {
System.out.println("我是对象销毁之前执行的方法");
}
}
- applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p" xmlns:comtext="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定自动扫描的包路径-->
<comtext:component-scan base-package="com.ls.entity"/>
</beans>
- 测试代码
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(applicationContext.getBean("user1"));
}
- 运行结果
可以看到,我们所有的属性,都可以通过注解的方式进行依赖的注入。