Spring优雅注册Bean的方式
1、Spring注册Bean
这篇先说明用法,下篇分析以下场景是如何将Bean注册进IOC容器的。1。1、使用Bean注解
这种用法在项目中是非常常见的,基本上是必有。我们来看下用法:ConfigurationpublicclassTestConfig{BeanpublicTestBeantestBean(){returnnewTestBean();}publicstaticclassTestBean{}}复制代码
这样一个Bean就注册进IOC容器了,Bean的名称默认是方法名,并且是不会转换大小写的,也就是假如你的方法名是TestBean(),那么Bean的名称就是TestBean。当然我们也可以使用name或者value指定Bean的名称,比如Bean(valuetestBean),如果二者同时存在则会报错。
我们来看下其他属性:
autowireCandidate:默认值是true。如果设置为false的话,那么通过byType的方式获取Bean就会报错,当然我们可以使用Resource注解获取。
initMethod:在Bean实例化后调用的初始化方法,值是Bean类中的方法名。
destroyMethod:在Bean要销毁时调用的清理方法,值是Bean类中的方法名。
Bean注解只能定义在Configuration类下吗?NONONO,它可以定义在任意能被IOC扫描的注解下,比如Component注解,至于区别,下篇再讲。1。2、使用ComponentScan注解组件扫描
先讲普通用法:ComponentScan(basePackagescom。rookie。spring。source。run。component)ConfigurationpublicclassTestConfig{}复制代码
使用ComponentScan组件扫描方式,它会扫描指定包下(包括子包)下的所有类,只要包含了Component、Configuration等Spring的声明注解,就会将Bean加入到IOC容器中。
深度用法:
ComponentScan注解中有两个这样的属性:includeFilters与excludeFilters,前一个是只包含规则,后一个是排除包含规则,他们的值是一个Filter注解的形式,Filter中的type有5中类型,分别如下。
1、ANNOTATION
第一种是以注解的形式包含或不包含,比如:ComponentScan(basePackagescom。rookie。spring。source。run。component,includeFiltersComponentScan。Filter(typeFilterType。ANNOTATION,classesConfiguration。class),useDefaultFiltersfalse)复制代码
这里边要配置useDefaultFiltersfalse禁用默认规则,因为默认规则是扫描所有,配只包含就没用了。这里的意思只扫描Configuration注解。
2、ASSIGNABLETYPE
这种是包含我们给定的类型,不管是给定的类型和子类都会被包含进IOC容器。publicclassTestBean1extendsTestBean{}publicclassTestBean{}ComponentScan(basePackagescom。rookie。spring。source。run。component,includeFilters{ComponentScan。Filter(typeFilterType。ANNOTATION,classesConfiguration。class),ComponentScan。Filter(typeFilterType。ASSIGNABLETYPE,classesTestBean。class)},useDefaultFiltersfalse)ConfigurationpublicclassTestConfig{}复制代码
然后我们发现testBean注册进去了,为什么我们不标注Component这样的注解实例也会被注册进IOC呢?因为ComponentScan会扫描包下所有文件,只要符合我们定义的过滤规则,它就会将Bean注册进IOC容器中。
3、ASPECTJ
ASPECTJ是使用aspectj表达式
4、REGEX
REGEX是使用正则表达式
5、CUSTOM
这种呢就是我们SpringBootApplication注解用到的方式了,我来解释一下具体规则:这种方式是可以自己自定义扫描规则,它接受一个实现TypeFilter接口的类。publicclassMyTypeFilterimplementsTypeFilter{parammetadataReader当前类的信息parammetadataReaderFactory可以获取其他类的信息return匹配结果throwsIOException异常Overridepublicbooleanmatch(MetadataReadermetadataReader,MetadataReaderFactorymetadataReaderFactory)throwsIOException{获取当前扫描类信息ClassMetadataclassMetadatametadataReader。getClassMetadata();returnclassMetadata。getClassName()。contains(com。rookie。spring。source。run。component。TestBean);}}ComponentScan(basePackagescom。rookie。spring。source。run。component,includeFilters{ComponentScan。Filter(typeFilterType。CUSTOM,classesMyTypeFilter。class)},useDefaultFiltersfalse)ConfigurationpublicclassTestConfig{}复制代码
当它扫描类的时候扫描到了TestBean,然后符合了我的匹配规则(也就是返回true)就注册进去了。1。3、使用Import注解
下面的例子中,我们直接看Spring源码的实现比较具有代表性一点。
我们点进EnableTransactionManagement注解中,发现了这个Import(TransactionManagementConfigurationSelector。class),它的作用就是将类导入,类会被注册进IOC容器中。
这个注解放置的位置要是Spring能扫描到的地方,不然Spring也不会主动去解析这个注解。
如果我们自己要使用注解的话,我们可以做个类似于EnableTransactionManagement的功能插拔式导入配置类,这样就可以实现动态开启一些Bean了。1。4、实现ImportSelector接口publicinterfaceImportSelector{Selectandreturnthenamesofwhichclass(es)shouldbeimportedbasedonthe{linkAnnotationMetadata}oftheimporting{linkConfiguration}class。String〔〕selectImports(AnnotationMetadataimportingClassMetadata);}复制代码
我们还是来看下TransactionManagementConfigurationSelector这个类,看下它的继承关系发现它间接性的实现了ImportSelector接口,主要看它实现的这个方法:OverrideprotectedString〔〕selectImports(AdviceModeadviceMode){switch(adviceMode){casePROXY:returnnewString〔〕{AutoProxyRegistrar。class。getName(),ProxyTransactionManagementConfiguration。class。getName()};caseASPECTJ:returnnewString〔〕{determineTransactionAspectClass()};default:returnnull;}}复制代码
这个方法的作用就是根据你返回的类全限定名(org。springframework。context。annotation。AutoProxyRegistrar)数组来创建Bean。
实现了ImportSelector的类也是需要使用Import导入。1。5、实现ImportBeanDefinitionRegistrar接口publicinterfaceImportBeanDefinitionRegistrar{Registerbeandefinitionsasnecessarybasedonthegivenannotationmetadataoftheimporting{codeConfiguration}class。pNotethat{linkBeanDefinitionRegistryPostProcessor}typesmayemnotemberegisteredhere,duetolifecycleconstraintsrelatedto{codeConfiguration}classprocessing。paramimportingClassMetadataannotationmetadataoftheimportingclassparamregistrycurrentbeandefinitionregistryvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry);}复制代码
这个我们来看下MapperScan(org。mybatis。spring。annotation)导入的MapperScannerRegistrar发现它实现了ImportBeanDefinitionRegistrar:publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){AnnotationAttributesmapperScanAttrsAnnotationAttributes。fromMap(importingClassMetadata。getAnnotationAttributes(MapperScan。class。getName()));if(mapperScanAttrs!null){this。registerBeanDefinitions(mapperScanAttrs,registry);}}复制代码
它的作用是拿到BeanDefinitionRegistryBean的定义信息,然后往里面加BeanDefinition就会将相应的对象注册进去,它更深入的就不说了,实际上就是解析下注解属性,然后扫描相应的包下的类注册Bean。我们自己搞个简单的。registry。registerBeanDefinition(testBean,newRootBeanDefinition(TestBean。class));复制代码
这样就注册了一个Bean名称是testBean类型是TestBean类型的Bean了。
如果注册的是一个有参构造器呢?那就这样:BeanDefinitionBuilderbeanDefinitionBuilderBeanDefinitionBuilder。rootBeanDefinition(TestBean。class);beanDefinitionBuilder。addConstructorArgValue(1);registry。registerBeanDefinition(testBean,beanDefinitionBuilder。getBeanDefinition());复制代码
addConstructorArgValue根据构造器参数的顺序去添加。
实现了ImportBeanDefinitionRegistrar的类也是需要使用Import导入。1。6、实现FactoryBean接口publicclassMyFactoryBeanimplementsFactoryBeanTestBean{OverridepublicTestBeangetObject()throwsException{returnnewTestBean();}OverridepublicClasslt;?getObjectType(){returnTestBean。class;}OverridepublicbooleanisSingleton(){returntrue;}}Import(MyFactoryBean。class)ConfigurationpublicclassTestConfig{}复制代码
然后TestBean就注册进去了,打印的时候我们发现Bean的名称是MyFactoryBean的全限定名,但是它的类型是TestBean类型的,如果想要获取MyFactoryBean类型的Bean的话,通过Bean名称为myFactoryBean就能获取到。1。7、使用spring。factories配置
在我们的SpringBoot项目中,一般都是只扫描主类下的所有类,然后将一些被特定注解标注的类加载到IOC容器,但是如果我们将包分离,我们又如何更加方便的将其他包的类加载进来呢?springboot提供了一种类似于Java的SPI(服务发现)机制spring。factories,只要在resources目录下创建METAINF文件夹,再创建spring。factories文件,然后再里面配置org。springframework。boot。autoconfigure。EnableAutoConfigurationcom。jylcloud。jyl。common。commondcs。config。RedissonManagerConfig复制代码
这样在导入当前包的就会自动扫描spring。factories文件,解析后将里面的一些类加载到IOC容器中。具体的实现代码在springcore的SpringFactoriesLoader类中。1。8、使用Component、Repository、Service、Controller、RestController
这些就不讲了。
创业者看准投资者和开店集团公司哪些灵性尽管扭转局势绝不是一个人的表演,但首席执行官的魄力和决心总会在此时凸现出来。没有成功的企业,只有时代的企业这是海尔CEO张瑞敏到香港科技大学讲座的题目。不过,自信和自满只有一线……
五行女孩名字合集适合女宝宝的高分起名不少家长在给孩子起名时,都比较注重五行属性上的搭配,其实这也是一种家长对孩子好的祝愿。所以我们这次就整理出了一些合适的名字,希望能给大家提供帮助,有时间的话可以来参考看看,或许……
一次成功的尝试失败是成功之母,每一件事,哪怕是一点点小事,都要经过勇敢的尝试,才可以去获得成功。我就有过一次成功的尝试,至今让我记忆犹新。那是我上二年级的一个暑假,因为我的期末考试成绩……
圆1、教材分析(1)知识结构(2)重点、难点分析重点:点和圆的三种位置关系,圆的有关概念,因为它们是研究圆的基础;五种常见的点的轨迹,一是对几何图形的深刻理解,……
234的乘法口诀教学反思范文本节课是在学习5的乘法口诀的基础上学习2、3、4的乘法口诀,根据学生自己已经有的知识经验,我先领着复习5的乘法口诀,说一说5口诀有几句,每相邻两句口诀相差几,为学生总结2、3、……
不识阅读理解答案不识(台湾张晓风)家人至亲,我们自以为极亲极爱了解的,其实我们所知道的也只是肤表的事件而不是刻骨的感觉。父亲的追思会上,我问弟弟:追诉平生,就由你来吧,你是儿子。弟弟沉吟……
胎动加快是怎么回事一般孕妇受剧烈的外伤时,胎动就会加快。专家分析异常胎动:一般来说,胎儿在孕妇的肚子里,有羊水的保护,可减轻外力的撞击,在孕妇不慎受到轻微的撞击时,不至于受到伤害。一……
这小夫妻的日子过那真叫乐1、酒这个东西,能不沾尽量别沾,刚才我们家就发生了一场酒后暴力事件,老婆喝醉了,把我打了一顿。2、老婆来大夷妈了包夷妈巾,儿子晚上睡觉包尿片,老婆要我也包上,不然显得不合……
奈何桥上你在等谁今生,只为寻找一个女子而来,一个可以让我钟情一生的女子,一个可以让我爱得挂怀的女子,她或许倾国倾城,但绝对风情万种。为这样的女子为此我在前世我就在佛前许下了心愿,于是我取……
日珥和耀斑哪个威力大太阳活动变化的最长久纪录是太阳黑子的变化。也有日珥和耀斑的发生,那么,大家是否了解日珥和耀斑哪个威力大?日珥是在太阳的色球层上产生的一种非常强烈的太阳活动,仿佛从太阳表面……
放松心情的新方法心理旅游心理旅游是一种新的放松心情的好方法。Psy525。cn心理旅游也许很多人都没有听说过就是和一个亦师亦友的心理医生一同上路,在大自然中敞开心扉,面对山水说心事,在旅途中接受……
九年级上册英语Unit2PeridOne的教学反思前言:1。为进一步深入开展新课程改革实验工作,以学生发展为本,培养学生自学能力,提高课堂教学效率,我校结合本校实际情况,学习江苏洋思中学先学后教、当堂训练教学方式以及江苏……