Spring注解 - 组件的注册

Spring Boot的出现极大的简化了我们的开发,让我们无需再写繁杂的配置文件,其正是利用了注解的便捷性,而Spring Boot又依赖于Spring,因此深入学习Spring的注解是十分必要的。
组件注册相关注解
@Configuration
写在类上,声明此类是一个配置类,替代xml文件
@Bean
作用:
给 IOC 容器中注册一个Bean,一般添加在方法上,组件类型为方法的返回值,id默认为方法名称
常用属性:
- value / name:指定组件的名称,如果不指定,默认是方法名
- initMethod:指定初始化方法
- destroyMethod:指定销毁方法
@ComponentScan
作用:
根据自定义的规则,自动扫描 IOC 容器中所有组件,在 jdk1.8 之后可以在一个类上定义多个@ComponentScan。
还有一个@ComponentScans注解,也可以在里面定义多个@ComponentScan
常用属性:
- value / basePackages:指定要扫描的包名
- @Filter:用于指定过滤的规则
- type:过滤类型
- FilterType.ANNOTATION:按照注解的方式
- FilterType.ASSIGNABLE_TYPE:按照给定的类型
- FilterType.ASPECTJ:使用ASPECTJ表达式
- FilterType.REGEX:使用正则表达式
- FilterType.CUSTOM:自定义类型
- value / classes:过滤值
- pattern:过滤规则,根据不同的过滤类型配置不同的规则
- type:过滤类型
- useDefaultFilters:是否使用默认过滤规则, 默认是 true
- includeFilters:指定扫描的时候只包含什么组件,需要配置
useDefaultFilters属性为false - excludeFilters:指定扫描的时候按照什么规则排除哪些组件
- lazyInit:懒加载
如何使用FilterType.CUSTOM自定义过滤规则?
public class MyTypeFilter implements TypeFilter {
/**
* 匹配方法,确定此过滤器是否与给定元数据描述的类匹配
* @param metadataReader 读取到的当前正在扫描的类的信息
* @param metadataReaderFactory 可以获取到其他任何类的信息
* @return true:匹配, false:不匹配
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路劲)
Resource resource = metadataReader.getResource();
//自定义匹配规则
String className = classMetadata.getClassName();
if(className.contains("Controller")){
return true;
}
return false;
}
}
@Scope
作用:
调整作用域
常用参数:
- value / scopeName
- singleton:单实例,ioc容器启动的时候就会调用方法,创建bean对象,以后每次获取都是直接从ioc容器中取(map.get())。
- prototype:多实例,ioc容器启动的时候不会去调用,当从ioc容器中获取bean对象的时候才会创建。
- request:同一次请求创建一个实例。
- session:同一个session范围创建一个实例。
- global session:全局session范围创建一个实例,一般用于集群。
@Lazy
懒加载,一般用于单例模式,容器启动的时候不会创建bean,第一次调用的时候才创建
@Conditional
作用:
按照一定条件进行判断,满足条件才注册bean,可以放在方法或类上,此注解在Spring Boot底层大量使用
常用参数:
- value:传入一个继承了Condition接口的类(可传入多个),类中定义自己需要的条件
@Import
作用:
给ioc容器中导入指定的组件
常用参数:
- value:传入指定类,id默认是全类名。可传入自定义类、ImportSelector 和 ImportBeanDefinitionRegistrar
用法:
在配置类上添加如下形式的注解即可
@Import({Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
ImportSelector
传入实现了 ImportSelector 接口的类,返回一个全类名数组,好处就是可以自定义需要导入的组件
public class MyImportSelector implements ImportSelector {
/**
* 自定义导入的组件
* @param importingClassMetadata 当前标注了@Import注解的类的所有注解信息
* @return 返回全类名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.spring.color.Blue", "com.spring.color.Yellow"};
}
}
打断点debug一下,可以看到参数的信息,的确是当前标注@Import的类上的注解信息

ImportBeanDefinitionRegistrar
手动注册bean到容器中,调用 registerBeanDefinition() 方法
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 当前标注了@Import注解的类的所有注解信息
* @param registry 容器中已注册组件的信息
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
int count = registry.getBeanDefinitionCount();
if(count > 10){
BeanDefinition beanDefinition = new RootBeanDefinition(Ten.class);
registry.registerBeanDefinition("ten", beanDefinition);
}
}
}
使用 FactoryBean 注册组件
自定义一个类,实现 FactoryBean 接口
public class FoodFactoryBean implements FactoryBean<Food> {
/**
* 获取实例对象
* @return
* @throws Exception
*/
@Override
public Food getObject() throws Exception {
return new Food();
}
/**
* 获取实例类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Food.class;
}
/**
* 是否单例,true:单例 false:多例
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
}
使用@Bean注册到容器
@Bean
public FoodFactoryBean foodFactoryBean(){
return new FoodFactoryBean();
}
测试一下
@Test
public void test2(){
Object bean = applicationContext.getBean("foodFactoryBean");
System.out.println("foodFactoryBean 的类型:" + bean.getClass());
}
运行结果如下,发现类型竟然不是 FoodFactoryBean ,使用@Bean注册的组件类型不是方法的返回值吗?实际上,FoodFactoryBean注册的时候调用的了 getObject() 方法,所以注册的是 Food 类
foodFactoryBean 的类型:class com.spring.bean.Food
那么如果想要获得 FoodFactoryBean 类怎么办呢?
看一下 BeanFactory 的源码,定义了一个成员变量 FACTORY_BEAN_PREFIX
这个变量用于取消引用 FactoryBean 实例,并将其与由 FactoryBean 创建的bean区别开。
例如,如果名为 test 的 bean 是 FactoryBean,则获取 &test 将返回工厂,而不是工厂返回的实例。

所以在getBean的时候,在 id 前加上 & 即可
@Test
public void test2(){
Object bean = applicationContext.getBean("&foodFactoryBean");
System.out.println("foodFactoryBean 的类型:" + bean.getClass());
}
总结
注册组件的方式:
- 包扫描 (@ComponentScan) + 组件注解(@Component / @Controller / @Service / @Repository)
- @Bean [导入第三方包里的组件]
- @Import [快速给容器中导入组件]
- 普通类:直接注册,id默认是全类名
- ImportSelector:返回需要注册组件的全类名数组
- ImportBeanDefinitionRegistrar: 手动注册组件到容器中
- 使用 spring 提供的 FactoryBean(工厂Bean)
- 默认获取的是 FactoryBean 调用getObject方法返回的对象
- 可以在获取Bean的时候在 id 前面加上 & 符号,获取 FactoryBean 本身
Spring注解 - 组件的注册的更多相关文章
- spring注解-组件注册
一.@Configuration+@Bean @Configuration:配置类==配置文件 @Bean:给容器中注册一个Bean:类型为返回值的类型,默认是用方法名作为id @Bean(" ...
- Spring注解 - AOP 面向切面编程
基本概念: AOP:Aspect Oriented Programming,即面向切面编程 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式 前置通知(@Before):在目标 ...
- Spring 注解原理(一)组件注册
Spring 注解原理(一)组件注册 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 当我们需要使用 Spring 提供的 ...
- spring注解扫描组件注册
最近对单点系统进行微服务拆分,被各个springboot的组件注册搞得云里雾里的.(有的是通过springboot的自动配置进IOC容器的,有的是自己添加构造方法添加进IOC容器.)决定抽时间将spr ...
- Spring注解开发-全面解析常用注解使用方法之组件注册
目录 1. @Configuration 2. @ComponentScan excludeFilters includeFilters 使用自定义TypeFilter 3. @Bean @Scope ...
- spring注解开发:容器中注册组件方式
1.包扫描+组件标注注解 使用到的注解如下,主要针对自己写的类 @Controller @Service @Repository @Component @ComponentScan 参考 spring ...
- Spring注解开发系列Ⅱ --- 组件注册(下)
1.@Import注册组件 @Import主要功能是通过导入的方式实现把实例加入springIOC容器中, /** * 给容器注册组件 * 1.包扫描+组件标注注解(@Controller,@Serv ...
- 【Spring注解开发】组件注册-使用@Configuration和@Bean给容器中注册组件
写在前面 在之前的Spring版本中,我们只能通过写XML配置文件来定义我们的Bean,XML配置不仅繁琐,而且很容易出错,稍有不慎就会导致编写的应用程序各种报错,排查半天,发现是XML文件配置不对! ...
- 【建议收藏】阿里P7总结的Spring注解笔记,把组件注册讲的明明白白
环境搭建 注解的方式是通过配置类的方式来注入组件,注解注入要比XML注入的方式简单,注解注入也需要在前者的基础上,添加一个spring-context的包,也是实际开发中常用的方式. 准备所需Jar包 ...
随机推荐
- mysql首次使用过程以及彻底卸载过程
安装过程: 步骤一: 安装mysql服务,使用命令行: yum install mysql-server 步骤二: 启动mysql服务: service mysqld start 确认msyql是否启 ...
- spring学习笔记四:AOP
AOP(Aspect Orient Programming),面向切面编程,是对面向对象编程OOP的一种补充 面向对象编程使用静态角度考虑程序的结构,而面向切面编程是从动态角度考虑程序运行过程 AOP ...
- IOC读取配置文件
1. 创建一个bean文件 package com.longteng.utils; import org.springframework.beans.factory.annotation.Value; ...
- Hexo博客部署
前些天使用wordpress程序搭建了个人网站,但感觉太重比较适合个人空间,所以这次介绍Hexo搭建免费博客,先提供官网给大家英文版的请点击这里,中文版的请点击这里,在安装一个Git,再是github ...
- 一个很粗糙的XXXX
改dnsrecon的代码改来改去都获取不到想要的结果,也不知道是不是py中的正则和PHP的有神马不一样的地方,但是用RegexBuddy测的时候是正确的,想不通啊想不通.果断不改了,自己动手PHP ...
- HDU 5894 hannnnah_j’s Biological Test【组合数学】
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5894 题意: 一个圆桌上有$n$个不同的位置,$m$个相同的人安排到这$n$个位置上,要求两人相邻的 ...
- Vizceral小白入门
Vizceral小白入门 接到一个任务,要求将N个program可视化,能一目了然查看当前爬虫状态.记得之前做测试时,一个queue service前端可视化效果不错,经询问是用vizceral开源框 ...
- 聊一聊MyBatis 和 SQL 注入间的恩恩怨怨
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...
- Centos +Docker 安装及仓库使用概述
1. Linux 系统学习Docker安装篇 这里我使用的Centos系统 安装Docker yum命令说明 即Yellowdog Update Modifier,是一种基于rpm的包管理工具 yu ...
- MVC07
1. 讲解ASP.net MVC的I/O操作 新建一个控制台程序,输入代码如下 using System; using System.IO; namespace IO { class Program ...