Spring注解 组件注册
组件注册
- 给容器中注册组件的方式:
- 包扫描+组件标注注解
(@Controller/@Service/@Repository/@Component)
适用于我们自己写的类 - @Bean
适用于导入第三方包里的组件 - @Import 快速给容器中导入一个组件
- 使用Spring提供的FactoryBean(工厂Bean)
@Bean @Configuration 给容器中注册组件
@Configuration 写在类上说明这是一个配置类,代替原来的xml文件
@Bean 就是给容器中注册一个Bean
- 类型(class):为返回值类型
- id:默认是用方法名作为id,也可以通过@Bean(“xxx”)指定id名为xxx
示例:
@Bean注解给容器添加的组件默认是单实例的,也就是只创建一次,以后每次获取得到的都是同一个Bean
如果要修改成多实例, 可以
用@Scope注解
@Scope 设置组件作用域
- 这个@Scope 等同于原来xml文件中 bean标签下的scope属性
- @Scope 可以取的值:
- prototype: 多实例的。
ioc容器启动不会调用方法创建对象,每次获取的时候才会创建方法调用对象;每次获取都会调这个方法 - singleton: 单实例的(默认值);
ioc容器启动就会调用方法创建对象放到ioc容器中,以后每次获取都是直接(map.get())从容器中拿
加上@lazy 注解后就是懒加载,容器启动不会创建,第一次获取Bean的时候才创建对象并初始化 - request: 同一次请求创建一个实例
- session: 同一个session创建一个实例
我们用@Scope 注解设置 组件可以修改组件的作用域,因为默认是单实例的我们要是想改成多实例的就可以用@Scope("prototype")
注解
修改过后可以看到得到的是false说明两次获取到的person不一样,是创建了两次对象
@ComponentScan 自动扫描组件
属性:
- value 指定要扫描的包
- includeFilters:扫描的时候只包含哪些 Filter[] 注意禁用掉useDefaultFilters
@ComponentScan(value = "com.atguigu",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})},useDefaultFilters = false)
- excludeFilters: 扫描的时候排除哪些 Filter[]
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}
@Filter
上面的includeFilters和excludeFilters都是通过Filter[] 来指定扫描的时候包含/不包含的 ,这个Filter也是一个注解
其中的type属性的值都是FilterType,FilterType包含的值如下:
-
FilterType.ANNOTATION: 按照注解
-
FilterType.ASSIGNABLE_TYPE 按照给定的类型
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookService.class})
-
FilterType.ASPECTJ
使用ASPECTJ表达式,基本不用 -
FilterType.REGEX 正则表达式
-
FilterType.CUSTOM 自定义规则
MyTypeFilter:
定义规则的类 要实现TypeFilter接口
结果
@Import 给容器中快速导一个组件
要导入组件的全类名
-
@Import(要导入到容器中的组件)
导入的id默认是全类名
ImportSelector
- ImportSelector
自定义类实现ImportSelector接口,重写selectImports方法,这个方法的返回值指定要导入到容器中的组件的全类名
AnnotationMetadata: 当前类的注解信息
ImportBeanDefinitionRegistrar
- ImportBeanDefinitionRegistrar 手动注册bean到容器中
我们可以自定义给容器中注入组件
自定义类实现ImportBeanDefinitionRegistrar接口,重写registerBeanDefinitions方法,
这个方法有两个参数:
- AnnotationMetadata: 当前类的注解信息
- BeanDefinitionRegistry
可以通过BeanDefinitionRegistry.registerBeanDefinition方法注册我们需要添加到容器的Bean
FactoryBean
- 创建工厂Bean 实现FactoryBean<>,泛型中放的就是 要创建的Bean的类型
要实现的getObject方法就是 我们获取对象调的方法
如果要通过application.getBean() 获取工厂对象本身,则需要给id前面加一个&标识
Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");//返回值是Color 调用的是getObject创建的对象
Object colorFactoryBean = applicationContext.getBean("&colorFactoryBean"); //返回值是ColorFactoryBean
@Conditional 按照条件注册Bean
@Conditional :
- @Conditional注解可以放在类上也可以放在方法上
- 放在类上
满足条件,这个类中配置的所有bean注册才能生效 - 放在方法上
满足条件,这个bean生效
- 放在类上
- 要传的Condition
matches 方法 的返回值如果是true,则条件匹配成功;是false,匹配失败。
两个参数:
- ConditionContext判断条件能使用的上下文(环境)
- AnnotatedTypeMetadata 注释信息
具体做法就是,要把判断的条件写在自己的条件类里实现Condition接口