Spring IOC容器组件注入的几种方式
整理一下之前Spring的学习笔记,大致有一下几种Spring注入到容器中的方法:
1)、配置在xml的方式。
2)、开启包扫描@ComponentScan使用@Component,@Service,@Controller,@Repository(其实后三个都继承@Component)注册组件到spring容器里面
3)、使用@Bean注入
4)、使用@Import快速导入组件
@Configuration
声明为配置类,与bean.xml一致
XML方式注入
Sping最开始的用法,先定义好xml文件,使用ClassPathXmlApplicationContext()加载指定xml文件就创建好容器了,当Bean过多的时候,使用xml配置就显得比较繁琐,所以在现在的大环境下,这种注入方法已经过时了,就简单的提一下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.test.SpringCoreTest.test00.bean.User"><property name="name" value="Tom"></property><property name="age" value="12"></property></bean></beans>
@ComponentScan
需和@Configuration注解一起使用,与xml当中的<context:component-scan base-package="" />一致,表示扫描指定包下的类将带有@Component注解的类全部扫描到容器当中
有几个常用的参数需了解一下:
basePackages: 扫描指定包下的类并且注入到spring容器里面
useDefaultFilters:是否使用默认过滤器,和excludeFilters、includeFilters配置一起使用
includeFilters:包含过滤器为过滤的内容,当useDefaultFilters为false的时候才生效
excludeFilters:去除指定过滤器过滤的内容,当useDefaultFilters为true的时候才能生效
过滤器为@ComponentScan的内部注解类@Filter:
classes:指定类,与type搭配使用
type:过滤器的类型org.springframework.context.annotation.FilterType.class枚举类中(共有五种,仅记录三种经常使用的类型)
ANNOTATION:指定过滤哪些注解,例如@Controller
ASSIGNABLE_TYPE:指定过滤哪些类
CUSTOM:自定义过滤器,可继承TypeFilter接口,实现match方法
示例:
public class SpringTest01Filter implements TypeFilter {/*** @param metadataReader 读取当前扫描类的信息* @param metadataReaderFactory 可以获取其他任何类的信息*/public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)throws IOException {//获取当前注解信息ClassMetadata classMetadata = metadataReader.getClassMetadata();//获取当前扫描类的信息String className = classMetadata.getClassName();System.out.println("====>>>>"+className);if(className.contains("er"))//如果当前扫描类信息包含er的时候,注入到Spring容器return true;elsereturn false;}}//配置类
@ComponentScan(basePackages="com.test.SpringCoreTest.test01.config",includeFilters= {@Filter(type = FilterType.CUSTOM,classes= {SpringTest01Filter.class})
},useDefaultFilters=true)
@Configuration
这里会有个问题,为什么在使用过滤器的时候对useDefaultFilters有要求?源码中解析:
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
//该段代码中获取了useDefaultFilters的值
//进入该类中
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;if (useDefaultFilters) {registerDefaultFilters();//useDefaultFilters为true时,该方法开启了注册默认过滤器的方法}setEnvironment(environment);setResourceLoader(resourceLoader);}//进入到registerDefaultFilters方法里面
protected void registerDefaultFilters() {//执行了当前方法重置了includeFilters包含的过滤器,导致带有Component注解的类都会加载到容器里面,所以在useDefaultFilters为true的情况下includeFilters失效的原因在此this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}
@Bean
需和@Configuration一起使用,容器中的key为方法名,bean为返回的对象,默认为单例。示例:
@Configuration
public class SpringConfig01 {@Beanpublic User user() {return new User();}//....
}
以下三个注解可以和@Bean一起使用:
@Scope
指定容器组件类型
prototype:多例模式,当容器创建时,并不会创建对象,而是在调用时创建一个新的对象
singleton:单例模式,容器创建时,对象也会创建
request:主要是针对web应用,每提交一次请求,都回去创建一个对象
session:针对web应用,创建一个session创建一个对象
@Lazy
懒加载只有当前组件第一次被调用的时候才会去创建对象,针对单例模式
@Conditional
可指定在某些条件下,才能将当前组件注入到容器,
参数为继承org.springframework.context.annotation.Condition.class的实现类
/*** @param context 可以使用ApplicationContext(上下文)* @param metadata 可以获取到注解信息*/public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {//获取到BeanFactoryConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//可获取环境参数,如jvm环境,spring环境等等Environment environment = context.getEnvironment();String osName = environment.getProperty("os.name");if(osName.contains("Windows"))//如果当前环境为window,则创建当前组件并加载到容器中return true;return false;}
@Import
快速导入组件,共三种形式,这个算是一个比较主要的注入方式吧,在Spring中,需要做一些扩展的时候都会需要用到这个,比如:mybatis-spring融合,开启AOP功能等使用的就是这里的第三种方式
1)、@Import(value = { Dog.class,Cat.class })//快速导入到容器中,以类的全路径作为bean的ID
2)、@Import(value = { SpringTest03ImportSelector.class })//实现ImportSelector接口
public class SpringTest03ImportSelector implements ImportSelector {public String[] selectImports(AnnotationMetadata importingClassMetadata) {//返回为类的全类名return new String [] {};//注意一下,这边必须返回一个空的数组,不然启动报错空指针异常}}//在源码org.springframework.context.annotation.ConfigurationClassParser.class类中
private Collection<SourceClass> asSourceClasses(String... classNames) throws IOException {List<SourceClass> annotatedClasses = new ArrayList<>(classNames.length);//这里的classNames为之前ImportSelector返回的数组,为null的话即报错for (String className : classNames) {annotatedClasses.add(asSourceClass(className));}return annotatedClasses;}
3)、@Import(value = { SpringTest03ImportBeanDefinitionRegistrar.class })//实现ImportBeanDefinitionRegistrar接口,所有的bean注册都会使用到该接口进行注册
/*** @param importingClassMetadata 当前类的注解信息 * @param registry BeanDefinition的注册类* 可做条件修改*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean b1 = registry.containsBeanDefinition("user");if(b1) {registry.registerBeanDefinition("pig", new RootBeanDefinition(Pig.class));}
Spring IOC容器组件注入的几种方式相关推荐
- Spring IOC (DI) 依赖注入的四种方式
依赖注入的四种方式: set 注入 赋值,默认使用的是set() 方法,依赖注入底层是通过反射实现的 <bean id="student" class="cust. ...
- 【Spring杂烩】探讨Spring向容器注册Bean的三种方式
探讨Spring向容器注册Bean的三种方式 重点了解@Import实现的三种子方式 前提概要 Spring向容器注册Bean的三种方式 通过@ComponentScan.@Componet 通过@B ...
- Spring系列之依赖注入的三种方式
目录 一.依赖注入方式 1.使用属性的setXXX方法注入 2.构造函数注入 (1)按类型匹配入参type (2)按索引匹配入参index (3)联合使用类型和索引匹配入参[type和index一起使 ...
- Spring详解-------依赖注入的三种方式实例详解
目录 1.什么是依赖注入 1.1类的关系 1.1.1 依赖关系(Dependency) 1.1.2 聚合(Aggregation) 1.2关系强度 2 为什么使用依赖注入 2.1开闭原则 2.1.1 ...
- Spring框架—IOC容器—属性赋值的几种方式
目录 一.常用的赋值方式 1.1 set注入 1.1.1 ApplicationContext.xml配置文件 1.1.2 测试类: 1.1.2 控制台输出: 1.2 构造注入 1.2.1 修改Stu ...
- 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式
每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...
- IoC(控制反转)的主要组件和注入的两种方式
一.IoC的主要组件: (1).Spring框架的两个最基本和最重要的包是org.springframework.beans.factory(该包中的主要接口是BeanFactory)和org.spr ...
- spring注入普通java类_普通java类如何取得注入spring Ioc容器的对象
[除了使用XML配置外,还可以选择使用基于注解(annotation)的配置方式,其依赖于字节码来织入组件.注解注入在XML注入之前完成,因此在XML配置中可以重载注解注入的属性. 一.建一个Spri ...
- Spring IOC容器的依赖注入流程(收集和注册、分析和组装)
Spring IOC容器的依赖注入流程 Spring IOC容器的依赖注入工作可以分为两个阶段: 阶段一:收集和注册 第一个阶段可以认为是构建和收集bean定义的阶段,在这个阶段中,我们可以通过XML ...
最新文章
- java 对象内存布局_Java--对象内存布局
- 【DND图形库】一、简介与环境配置
- This application failed to start because it could not find or load the Qt platform plugin xcb in
- 使用 Azure Container Registry 储存镜像
- java 的几种对象 (PO,VO,DAO,BO,POJO) 解释
- python写文件格式转换程序_python实现txt文件格式转换为arff格式
- 字符串转换 BSTR/LPSTR/LPWSTR/Char
- Mysql学习总结(63)——Mysql数据库架构方案选择与分析
- Struts2-02-OGNL及值栈
- C# 算法之选择排序
- 对个人来说,最好的记账方法是什么?
- 【一起学Rust】Rust介绍与开发环境搭建
- 求正整数2和n之间的完全数
- 详解浏览器中的粘贴事件 paste onpaste 事件
- 同样是学编程,为什么别人十几岁就成了黑客,而你还在做码农
- Tesseract-OCR -01-Tesseract 介绍
- 一款 API 测试神器,非常强
- linux添加了路径还是不能调用_166个最常用的Linux命令,哪些你还不知道?
- IE if注释判断( [if gte IE 8] )的解释网上的完全乱七八糟啊!
- 第一课 request传参
热门文章
- modern android5.1,Modern摩登印
- 地图 插件 html 经纬度,如何往地图位置(经纬度)选择插件页面传递经纬度
- C语言编杂志程序,c语言程序错误修改
- 校友会2019中国大学计算机,校友会2019中国计算机类一流专业排名,清华大学排名第一...
- idea cloud bootstrap是啥_application.yml与bootstrap.yml的区别
- mybatis if test 判断参数_什么?你还在if判断参数?Spring Boot 注解进行参数校验真香...
- Windows 10如何消除文件夹右上角的“相对箭头”?
- java类构造方法成员方法练习_面向对象方法论总结 练习(一)
- python 学习2 /输入/ 输出 /列表 /字典
- gradle 查看依赖类库版本_Android studio中查看依赖的第三方库的历史版本和最新版本...