Spring 基于注解标识和扫描Bean

1. 使用注解标识Bean组件

标识Bean组件的注解有四个:

  • @Respository:标识持久化层(Dao层)组件。常用来标识XxxDao/XxxRepository
  • @Service:标识业务逻辑层组件。常用来标识XxxService
  • @Controller:标识控制器组件。常用来标识XxxServlet/XxxController
  • @Component:标识普通组件。

1.1. 注解和XML使用场景

用注解简洁又优雅。如果是自己写的类,尽量直接用注解

如果引用了其它依赖,但是依赖包中的类没有加注解,你还想要把这些类注册到IOC容器中,就只能用xml配置的方式。毕竟你不能直接修改源码,加上组件注册。

注解和xml配置可以结合使用

1.2. 标识流程

编写Bean,添加组件注解

1
2
3
4
5
6
@Data
@Component // 添加组件注解
public class Person {
private String name;
private Integer age;
}

配置组件扫描

1
2
<!-- 扫描指定包及其子包下 所有带有组件注解的Bean -->
<context:component-scan base-package="demo.spring.bean"/>

编写测试方法,从容器中取出Bean

1
2
3
4
5
6
7
8
9
10
@Test
public void test() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过类对象获取
Person person1 = ioc.getBean(Person.class);
// 获取名称获取,Bean的默认名称是 类名首字母小写,即Person => person
Person person2 = (Person) ioc.getBean("person");
// 默认是单实例的
System.out.println(person1 == person2); // true
}

1.3. 组件命名

组件命名规则:

  • 默认情况:组件简单类名首字母小写作为Bean的id
  • 使用组件注解的value属性指定Bean的id
1
2
3
4
5
6
@Data
@Component("hello") // 命名
public class Person {
private String name;
private Integer age;
}
1
2
3
4
5
6
7
@Test
public void test() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person1 = ioc.getBean(Person.class);
Person person2 = (Person) ioc.getBean("aaa");
System.out.println(person1 == person2);
}

1.4. 设置组件作用域

  • @Scope(value=”singleton”)
  • @Scope(value=”prototype”)
1
2
3
4
5
6
7
@Data
@Component
@Scope("prototype") // 多实例
public class Person {
private String name;
private Integer age;
}

2. 组件扫描

扫描单个包下的组件

1
2
<!-- 扫描指定包及其子包下 所有带有组件注解的class -->
<context:component-scan base-package="demo.spring.bean"/>

扫描多个包下的组件

1
2
<!-- 扫描多个包用逗号分隔 -->
<context:component-scan base-package="demo.spring.bean,demo.spring.service"/>

多个context:component-scan不建议共存,可能会出现奇怪的问题,暂时没有研究

1
2
3
<!-- 不建议写多个context:component-scan  -->
<context:component-scan base-package="demo.spring.bean"/>
<context:component-scan base-package="demo.spring.service"/>

2.1. context:exclude-filter排除扫描

排除某个class

1
2
3
4
<context:component-scan base-package="demo.spring.bean">
<!-- 排除Car -->
<context:exclude-filter type="assignable" expression="demo.spring.bean.Car"/>
</context:component-scan>

排除某个注解

1
2
3
4
<context:component-scan base-package="demo.spring.bean">
<!-- 排除@Service -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>

多个context:exclude-filter可以共存

1
2
3
4
5
6
<context:component-scan base-package="demo.spring.bean">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="assignable" expression="demo.spring.bean.Car"/>
<context:exclude-filter type="assignable" expression="demo.spring.bean.Person"/>
</context:component-scan>

特别注解,如果排除@Component,相当于还排除了@Repository、@Service、@Controller

2.2. context:include-filter包含扫描

包含某个注解

1
2
3
4
<!-- use-default-filters设置为false,context:component-scan默认不会扫描到任何class -->
<context:component-scan base-package="demo.spring.bean" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

包含某个class

1
2
3
<context:component-scan base-package="demo.spring.bean" use-default-filters="false">
<context:include-filter type="assignable" expression="demo.spring.bean.Person"/>
</context:component-scan>

多个context:include-filter可以共存

1
2
3
4
<context:component-scan base-package="demo.spring.bean" use-default-filters="false">
<context:include-filter type="assignable" expression="demo.spring.bean.Person"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

panchaoxin wechat
关注我的公众号
支持一下