Spring IOC扫描器与注册器
核心接口:
组件扫描器:
开发过程中,需要根据需求加载必要的bean,排除指定bean
设定组件扫描加载过滤器:
名称:@ComponentScan
类型:类注解
位置:类定义上方
作用:设置spring配置加载类扫描规则
范例:
@ComponentScan(value="com.itzhuzhu", //设置基础扫描路径excludeFilters = //设置过滤规则,当前为排除过滤@ComponentScan.Filter( //设置过滤器type= FilterType.ANNOTATION, //设置过滤方式为按照注解进行过滤classes=Repository.class) //设置具体的过滤项,过滤所有@Repository修饰的bean)
public class SpringConfig(){}
includeFilters
:设置包含性过滤器
excludeFilters
:设置排除性过滤器
type
:设置过滤器类型
自定义组件过滤器:
名称:TypeFilter
类型:接口
作用:自定义类型过滤器
范例:
@ComponentScan(value="com.itzhuzhu",excludeFilters =@ComponentScan.Filter(type= FilterType.CUSTOMclasses=MyTypeFilter.class) )
public class SpringConfig{}
public class MyTypeFilter implements TypeFilter {@Override//加载的类满足要求,匹配成功public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {//通过参数获取加载的类的元数据ClassMetadata classMetadata = metadataReader.getClassMetadata();//通过类的元数据获取类的名称String className = classMetadata.getClassName();//如果加载的类名满足过滤器要求,返回匹配成功if(className.equals("com.itheima.service.impl.UserServiceImpl")){//返回true表示匹配成功,返回false表示匹配失败。此处仅确认匹配结果,不会确认是排除还是加入,排除/加入由配置项决定,与此处无关return true;}return false;}
}
自定义导入器:
- bean只有通过配置才可以进入spring容器,被spring加载并控制,导入器可以不通过bean的方式加载
配置bean的方式如下:
- XML文件中使用标签配置
- 使用@Component及衍生注解配置
- 企业开发过程中,通常需要配置大量的bean,需要一种快速高效配置大量bean的方式
ImportSelector
名称: ImportSelector
类型:接口
作用:自定义bean导入器
范例:
配置文件:
ClassName=com.itzhuzhu.dao.impl.AccountDaoImp,com.itzhuzhu.dao.impl.BookDaoImpl
path=com.itzhuzhu.dao.impl.*
public class CustomerImportSelector implements ImportSelector {private String expression;public CustomerImportSelector(){try {//初始化时指定加载的properties文件名Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties");//设定加载的属性名expression = loadAllProperties.getProperty("path");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//1.定义扫描包的名称String[] basePackages = null;//2.判断有@Import注解的类上是否有@ComponentScan注解if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {//3.取出@ComponentScan注解的属性Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());//4.取出属性名称为basePackages属性的值basePackages = (String[]) annotationAttributes.get("basePackages");}//5.判断是否有此属性(如果没有ComponentScan注解则属性值为null,如果有ComponentScan注解,则basePackages默认为空数组)if (basePackages == null || basePackages.length == 0) {String basePackage = null;try {//6.取出包含@Import注解类的包名basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();} catch (ClassNotFoundException e) {e.printStackTrace();}//7.存入数组中basePackages = new String[] {basePackage};}//8.创建类路径扫描器ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);//9.创建类型过滤器(此处使用切入点表达式类型过滤器)TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader());//10.给扫描器加入类型过滤器scanner.addIncludeFilter(typeFilter);//11.创建存放全限定类名的集合Set<String> classes = new HashSet<>();//12.填充集合数据for (String basePackage : basePackages) {scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName()));}//13.按照规则返回return classes.toArray(new String[classes.size()]);}
}
@Configuration
@ComponentScan("com.itzhuzhu")
@Import(CustomeImportBeanDefinitionRegistrar.class) // 加载导入器
public class SpringConfig {}
自定义注册器:
名称:ImportBeanDefinitionRegistrar
类型:接口
作用:自定义bean定义注册器
范例:
public class CustomeImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {private String expression;public CustomeImportBeanDefinitionRegistrar(){try {//初始化时指定加载的properties文件名Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties");//设定加载的属性名expression = loadAllProperties.getProperty("path");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//1.定义扫描包的名称String[] basePackages = null;//2.判断有@Import注解的类上是否有@ComponentScan注解if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {//3.取出@ComponentScan注解的属性Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());//4.取出属性名称为basePackages属性的值basePackages = (String[]) annotationAttributes.get("basePackages");}//5.判断是否有此属性(如果没有ComponentScan注解则属性值为null,如果有ComponentScan注解,则basePackages默认为空数组)if (basePackages == null || basePackages.length == 0) {String basePackage = null;try {//6.取出包含@Import注解类的包名basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();} catch (ClassNotFoundException e) {e.printStackTrace();}//7.存入数组中basePackages = new String[] {basePackage};}//8.创建类路径扫描器ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);//9.创建类型过滤器(此处使用切入点表达式类型过滤器)TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader());//10.给扫描器加入类型过滤器scanner.addIncludeFilter(typeFilter);//11.扫描指定包scanner.scan(basePackages);}
}
bean初始化过程解析:
bean初始化过程解析:
BeanFactoryPostProcessor
作用:定义了在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处理
运行时机:当前操作用于对工厂进行处理,仅运行一次
BeanPostProcessor
作用:定义了所有bean初始化前后进行的统一动作,用于对bean进行创建前业务处理与创建后业务处理
运行时机:当前操作伴随着每个bean的创建过程,每次创建bean均运行该操作
InitializingBean
作用:定义了每个bean的初始化前进行的动作,属于非统一性动作,用于对bean进行创建前业务处理
运行时机:当前操作伴随着任意一个bean的创建过程,保障其个性化业务处理
注意:上述操作均需要被spring容器加载才可以运行
bean初始化过程解析:
package config.postprocessor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;public class MyBeanFactory implements BeanFactoryPostProcessor {@Override//工厂后处理bean接口核心操作public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("bean工厂制作好了,还有什么事情需要处理");}
}
package config.postprocessor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBean implements BeanPostProcessor {@Override//所有bean初始化前置操作public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("bean之前巴拉巴拉");System.out.println(beanName);return bean;}@Override//所有bean初始化后置操作public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("bean之后巴拉巴拉");return bean;}
}
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.InitializingBean;public class EquipmentDaoImpl implements EquipmentDao,InitializingBean {public void save() {System.out.println("equipment dao running...");}@Override//定义当前bean初始化操作,功效等同于init-method属性配置public void afterPropertiesSet() throws Exception {SqlSessionFactoryBean fb;System.out.println("EquipmentDaoImpl......bean ...init......");}
}
繁琐的bean初始化过程处理:
FactoryBean
- 对单一的bean的初始化过程进行封装,达到简化配置的目的
FactoryBean与BeanFactory区别
FactoryBean:封装单个bean的创建过程
BeanFactory:Spring容器顶层接口,定义了bean相关的获取操作
Spring IOC扫描器与注册器相关推荐
- 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式
每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...
- Spring:Spring IOC注解方式注册beanDefinition
文章目录 1.美图 2.概述 3.案例 3.1 案例1 4.容器初始化 5.AnnotationConfigApplicationContext 5.1 registerBean 5.1.1 clas ...
- Spring IOC流程源码分析
一.Spring 核心容器 IOC初始化过程 Spring 核心之 IOC 容器初体验 IOC 与 DI IOC(Inversion of Control)控制反转:所谓控制反转,就是把原先我们代码里 ...
- 21.手绘Spring IOC运行时序图
1.再谈IOC与 DI IOC(lnversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创 建.依赖的代码,反转给容器来帮忙实现.那么必然的我们需要创建一 ...
- Spring:源码解读Spring IOC原理
2019独角兽企业重金招聘Python工程师标准>>> 一.什么是Ioc/DI? IOC容器:主要是完成了 完成对象的创建和依赖的管理注入等. 先从我们自己设计这样一个视角来考虑: ...
- 一步一步手绘Spring IOC运行时序图二(基于XML的IOC容器初始化)
相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...
- JavaEE之Spring框架(Spring IOC)的使用
六.Spring框架 6.1 Spring框架的概念 Spring 是众多开源java项目中的一员,基于分层的javaEE应用一站式轻量级开源框架,主要核心是 IOC(控制反转/依赖注入)与 AOP( ...
- Spring IOC容器的依赖注入流程(收集和注册、分析和组装)
Spring IOC容器的依赖注入流程 Spring IOC容器的依赖注入工作可以分为两个阶段: 阶段一:收集和注册 第一个阶段可以认为是构建和收集bean定义的阶段,在这个阶段中,我们可以通过XML ...
- spring ioc的包的扫描(基于注解)
一.包扫描初始步骤源码分析 AnnotationConfigApplicationContext aac =new AnnotationConfigApplicationContext("c ...
最新文章
- 【BZOJ4653】[Noi2016]区间 双指针法+线段树
- [react-router] React-Router怎么设置重定向?
- 阿里CTO张建锋:明年双11将大规模应用含光AI芯片
- Hive内部表与外部表区别详细介绍
- mysql改根用户_MySQL数据库中复位根用户密码的方法 | 很文博客
- 知到网课创新创业学考试试题答案分享!
- 【过程记录】ArcGIS Pro打开.osgb文件
- 云计算机教室优缺点,云教室和传统机房的区别,终于有人把它说清了
- 个人sublime定制
- 都在谈中台,究竟什么是中台?
- C C++实现网络验证和本地验证
- iOS 新浪新闻首页卡片滚动特效实现
- Siggraph三角网格变形之拉普拉斯变换
- JavaWeb技术内幕二:Java IO工作机制
- python 调用Google Translate API进行翻译
- 阿尔法蛋机器人tf卡_阿尔法蛋机器人哪款好适合几岁孩子,超能蛋早教机真实效果评测(价格309元)...
- 使用Burp,nbsp;Sqlmap进行自动化SQL注入渗透测试
- 机器阅读理解技术初探Bi-DAF
- 《Google软件测试之道》—第2章2.5节与Web Driver的创建者Simon Stewart的对话
- matlab中图像的阈值分割,基于MATLAB的图像阈值分割技术汇总
热门文章
- java使用计算器完成加法、减法运算
- 职高学计算机走单招是,职高学生不用愁了,还有机会上本科,走“单招”或是最佳途径!...
- IDEA创建.properties文件
- python matplotlib模块教程_Python中的Matplotlib模块入门教程
- android 生成 资源文件,SVG-Android开源库——SVG生成Vector资源文件的编辑预览工具...
- oracle vitu,Supply Chain Management (SCM) a Manufacturing | Oracle Česká Republika
- 【Python】常用的数据类型介绍以及它们之间相互转化
- matplotlib的基本使用 附python代码详细讲解(基本图的绘制、样式、简单函数的使用)
- (python3.8)pygraphviz的下载安装配置(在python下)最新
- java文件名判断练习