Spring - 组件注册(一)
组件注册
@Configuration 和 @Bean
- 在 Spring 中配置类就相当于配置文件
import cn.lwjppz.entites.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置类 == 配置文件
*/
@Configuration // 告诉 Spring 这是一个配置类
public class MainConfig {
/**
* 给容器注册一个 Bean ,类型为返回值类型,id默认使用方法名作为id
* 也可给@Bean中传入value参数自定义id
* @return user实例
*/
// @Bean("user01")
@Bean
public User user() {
return new User(1, "lwjppz", 20);
}
}
- 测试类
import cn.lwjppz.config.MainConfig;
import cn.lwjppz.entites.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
@Test
public void test() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
User user = context.getBean(User.class);
System.out.println(user);
String[] names = context.getBeanNamesForType(User.class);
for (String name : names) {
System.out.println(name);
}
}
}
- 测试结果
@ComponentScan - 自动扫描组件&指定扫描规则
- 新建UserController、UserDao、UserService,分别加上@Controller,@Repository,@Service注解
- 测试
@Test
public void test2() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
指定包扫描规则
1. 指定排除规则
// excludeFilters Filter[] 扫描的时候按照指定的规则排除指定的组件
// 排除加了 @Controller 和 @Service 注解的组件
@ComponentScan(value = "cn.lwjppz", excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})})
效果:
很明显和之前相比少了 userController 和 userService。
2. 指定包含规则
// includeFilters Filter[] 扫描的时候只需要包含哪些组件
// 只扫描加了 @Controller 组件的组件
@ComponentScan(value = "cn.lwjppz", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = Controller.class)}, useDefaultFilters = false)
注意:使用 includeFilters 时要排除 Spring 默认的 Filters,需在 @ComponentScan 中加入 useDefaultFilters = false
效果:
现在就只有加了 @Controller 的组件被包含进来了
3. 也可使用 @ComponentScans 来指定多个扫描规则
@ComponentScans({
@ComponentScan(value = "cn.lwjppz", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = Controller.class)}, useDefaultFilters = false)
})
效果是和之前的一样的。
4. 自定义规则
/**
* FilterType.ANNOTATION 按照注解
* FilterType.ASSIGNABLE_TYPE 按照给定的类型
* FilterType.ASPECTJ 使用 ASPECTJ 表达式
* FilterType.REGEX 使用正则表达式
* FilterType.CUSTOM 使用自定义规则
*/
注意:自定义 Filter 需实现 TypeFilter 接口
@Scope - 设置组件作用域
@Configuration
public class MainConfig2 {
/**
* 默认是单实例的
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE singleton
* @see ConfigurableBeanFactory#SCOPE_SINGLETON prototype
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session
* @return
*
* singleton 单实例(默认值) IOC容器启动后会去调用方法创建对象,放入容器中
* 以后每次获取都是从容器中拿(map.get())
* prototype 多实例 IOC容器启动后并不会去调用方法创建对象放入容器中
* 每次获取的时候才会调用方法创建对象,所以每次获取的对象都不相同
* request 同一次请求创建一个实例
* session 同一次 session 创建一个实例
*/
@Scope("singleton")
@Bean
public User user() {
return new User(1, "lisi", 20);
}
}
测试:
@Test
public void test3() {
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
User bean1 = context.getBean(User.class);
User bean2 = context.getBean(User.class);
System.out.println(bean1 == bean2);
}
换成 prototype 之后
@Lazy - Bean懒加载
单实例bean,默认在容器启动的时候创建对象。 懒加载,容器启动时不创建对象,在第一次使用(获取)bean的时候创建,并初始化。