Spring注解详解包扫描bean注册
一. @Configuration 配置
告诉Spring容器这是一个配置类 ==xml配置
二. @ComponentScan 包扫描
说明:
//value:指定要扫描的包 //按照规则指定需要关闭默认规则,设置 useDefaultFilters=false; //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件 //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件 //FilterType.ANNOTATION:按照注解 //FilterType.ASSIGNABLE_TYPE:按照给定的类型; //FilterType.ASPECTJ:使用ASPECTJ表达式 //FilterType.REGEX:使用正则指定 //FilterType.CUSTOM:使用自定义规则
使用例子在配置类上添加:
@ComponentScan(value = {"com.willow"}, includeFilters = { @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class}), //添加 RController 注解的组件 @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes={persion.class}), //添加 类型为persion 注解的组件 @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}), // 自定义注解的规则 @ComponentScan.Filter(type = FilterType.ANNOTATION,classes={Repository.class,Controller.class}) //添加 Repository和,Controller 注解的组件 }, useDefaultFilters = false //includeFilters 设置 useDefaultFilters=false; excludeFilters 设置 useDefaultFilters=true ) //包扫描
自定义规则扫描 MyTypeFilter:
package com.willow.config; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; public class MyTypeFilter implements TypeFilter { /** * metadataReader:读取到的当前正在扫描的类的信息 * metadataReaderFactory:可以获取到其他任何类信息的 */ @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(); System.out.println("--->"+className); if(className.contains("er")){ //类名称包含“er”的 返回true,注册到IOC容器中 return true; } return false; //不注册 } }
三. @Conditional 注解
在类上添加:满足当前条件,这个类中配置的所有bean注册才能生效;
方法上添加:满足当前条件,这个方法的bean注册才能生效;
@Conditional({WindowsCondition.class})
自定义condition 实现接口
package com.willow.condition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotatedTypeMetadata; public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // TODO是否Windows系统 //1、能获取到ioc使用的beanfactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //2、获取类加载器 ClassLoader classLoader = context.getClassLoader(); //3、获取当前环境信息 Environment environment = context.getEnvironment(); //4、获取到bean定义的注册类 BeanDefinitionRegistry registry = context.getRegistry(); ResourceLoader resourceLoader = context.getResourceLoader(); Class<? extends ConditionContext> aClass = context.getClass(); String property = environment.getProperty("os.name"); //可以判断容器中的bean注册情况,也可以给容器中注册bean boolean definition = registry.containsBeanDefinition("person"); if(property.contains("Windows")){ //如果是Windows 系统,这个组件才注册 return true; } return false; } }
四、给容器中注册组件方法
/** 给容器中注册组件方法: 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类] 2)、@Bean[导入的第三方包里面的组件] 3)、@Import[快速给容器中导入一个组件] 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名 2)、ImportSelector:返回需要导入的组件的全类名数组; 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中 4)、使用Spring提供的 FactoryBean(工厂Bean); 1)、默认获取到的是工厂bean调用getObject创建的对象 Object bean2 = applicationContext.getBean("colorFactoryBean"); 得到的bean 是colorFactoryBean.getObject()方法中创建的对象 2)、要获取工厂Bean本身,我们需要给id前面加一个& &colorFactoryBean 例子:Object bean4 = applicationContext.getBean("&colorFactoryBean"); System.out.println(bean4.getClass()); */
4.1 包扫描+组件标注注解
在类上添加:@Controller/@Service/@Repository/@Component
4.2 @Bean 注解 在容器中注册一个bean
/* * Scope * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype * @see ConfigurableBeanFactory#SCOPE_SINGLETON singleton * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST web环境下 同一个reqeust 一个实例 * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION web环境下 同一个session 一个实例 * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。 * 每次获取的时候才会调用方法创建对象; * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。 * 以后每次获取就是直接从容器(map.get())中拿, * request:同一次请求创建一个实例 * session:同一个session创建一个实例 * * 懒加载: @Lazy * 单实例bean:默认在容器启动的时候创建对象; * 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化; * */ //默认是单实例的 //@Scope("prototype") @Lazy @Bean //(name = "myPersion") //创建一个bean ,name指定bean的Id,默认Id为方法名称 public Persion persion() { System.out.println("给容器中添加Person...."); return new Persion(1, "willow", "28"); }
4.3 配置类上@Import
4.3.1 @Import导入指定的类
@Import({Color.class}) //导入组件,id默认是组件的全类
4.3.2 实现ImportSelector接口
@Import({Color.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class}) //导入组件,id默认是组件的全类名
接口定义:
import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; //自定义逻辑返回需要导入的组件 public class MyImportSelector implements ImportSelector { //返回值,就是到导入到容器中的组件全类名 //AnnotationMetadata:当前标注@Import注解的类的所有注解信息 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //方法不要返回null值 // return null; return new String[]{"com.willow.bean.Red"}; } }
4.3.3 实现ImportBeanDefinitionRegistrar接口 ,手动添加到容器中去
import com.willow.bean.RainBow; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * AnnotationMetadata:当前类的注解信息 * BeanDefinitionRegistry:BeanDefinition注册类; * 把所有需要添加到容器中的bean;调用 * BeanDefinitionRegistry.registerBeanDefinition手工注册进来 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean definition = registry.containsBeanDefinition("com.willow.bean.Red"); boolean definition2 = registry.containsBeanDefinition("com.willow.bean.Blue"); if(definition ){ //指定Bean定义信息;(Bean的类型,Bean。。。) RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); //注册一个Bean,指定bean名 registry.registerBeanDefinition("rainBow", beanDefinition); } } }
4.4 使用Spring提供的 FactoryBean(工厂Bean)
1.实现FactoryBean 接口
import org.springframework.beans.factory.FactoryBean; //创建一个Spring定义的FactoryBean public class ColorFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return new Color(); } @Override public Class<?> getObjectType() { return Color.class; } //是否单例 //true 这个bean 是单实例,在容器中保存一份 //false 多实例的, @Override public boolean isSingleton() { return false; } }
2.注册 ColorFactoryBean 组件
@Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); }
五、配置类:
package com.willow.config; import com.willow.bean.Color; import com.willow.bean.ColorFactoryBean; import com.willow.bean.Persion; import com.willow.bean.Red; import com.willow.condition.LiunxCondition; import com.willow.condition.MyImportBeanDefinitionRegistrar; import com.willow.condition.MyImportSelector; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.*; import org.springframework.core.type.AnnotationMetadata; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; //类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效; //@Conditional({LiunxCondition.class}) @Configuration //告诉Spring容器这是一个配置类 @ComponentScan(value = {"com.willow"}, includeFilters = { /* @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class}), //添加 RController 注解的组件 @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes={persion.class}), */ //添加 类型为persion 注解的组件 @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}) // 自定义注解的规则 // , @ComponentScan.Filter(type = FilterType.ANNOTATION,classes={Repository.class,Controller.class}) //添加 Repository和,Controller 注解的组件 }, useDefaultFilters = false //includeFilters 设置 useDefaultFilters=false; excludeFilters 设置 useDefaultFilters=true ) //包扫描 //@ComponentScan value:指定要扫描的包 //按照规则指定需要关闭默认规则,设置 useDefaultFilters=false; //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件 //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件 //FilterType.ANNOTATION:按照注解 //FilterType.ASSIGNABLE_TYPE:按照给定的类型; //FilterType.ASPECTJ:使用ASPECTJ表达式 //FilterType.REGEX:使用正则指定 //FilterType.CUSTOM:使用自定义规则 @Import({Color.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class}) //导入组件,id默认是组件的全类名 public class SpringConfig { /* * Scope * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype * @see ConfigurableBeanFactory#SCOPE_SINGLETON singleton * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST web环境下 同一个reqeust 一个实例 * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION web环境下 同一个session 一个实例 * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。 * 每次获取的时候才会调用方法创建对象; * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。 * 以后每次获取就是直接从容器(map.get())中拿, * request:同一次请求创建一个实例 * session:同一个session创建一个实例 * * 懒加载: @Lazy * 单实例bean:默认在容器启动的时候创建对象; * 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化; * */ //默认是单实例的 //@Scope("prototype") @Lazy @Bean //(name = "myPersion") //创建一个bean ,name指定bean的Id,默认Id为方法名称 public Persion persion() { System.out.println("给容器中添加Person...."); return new Persion(1, "willow", "28"); } /** * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean * @return */ @Conditional(LiunxCondition.class) @Bean("myPersion") //创建一个bean ,name指定bean的Id,默认Id为方法名称 public Persion liunx() { System.out.println("给容器中添加Person...."); return new Persion(1, "liunx", "58"); } /** * 给容器中注册组件方法: * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类] * 2)、@Bean[导入的第三方包里面的组件] * 3)、@Import[快速给容器中导入一个组件] * 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名 * 2)、ImportSelector:返回需要导入的组件的全类名数组; * 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中 * 4)、使用Spring提供的 FactoryBean(工厂Bean); * 1)、默认获取到的是工厂bean调用getObject创建的对象 * Object bean2 = applicationContext.getBean("colorFactoryBean"); * 得到的bean 是colorFactoryBean.getObject()方法中创建的对象 * 2)、要获取工厂Bean本身,我们需要给id前面加一个& * &colorFactoryBean * 例子:Object bean4 = applicationContext.getBean("&colorFactoryBean"); * System.out.println(bean4.getClass()); */ @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } }
六、测试类:
import com.willow.bean.Persion; import com.willow.config.SpringConfig; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class AppTest { /** * 注解的方式 */ ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); @Test public void test03() { /** * 获取容器中所有的bean */ String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames(); for (String beanName : beanDefinitionNames) { System.out.println("########beanDefinitionNames_Annotation_bean_name:" + beanName); } Persion persion= annotationConfigApplicationContext.getBean(Persion.class); Persion persion01= annotationConfigApplicationContext.getBean(Persion.class); System.out.println("判断bean相等:"+persion==persion01+""); // @Scope("prototype") 不相等 ,单例:singleton 时候相等 } }
Spring注解详解包扫描bean注册相关推荐
- spring注解详解与用法(总览)
这篇文章收集了我写的所有的spring注解的详细说明与用法,点击可以跳转到对应文章,此文章会不断更新 spring注解详解与用法(1)最基础也是最常见的如下所示,详情点击这里 @Controller/ ...
- Spring注解详解
概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...
- Spring实现自动装配(spring注解详解)和手动注入比较
概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...
- Spring 注解详解
使用注解来构造IoC容器 在spring 3.0中,通过@controller标注即可将class定义为一个controller类.为使spring能找到定义为controller的bean,需要在a ...
- spring注解详解与用法(3)切面环绕
导航:更多的spring注解标签点击这里 声明了切面类我们还需要定义切面的内容面向切面编程是spring的一个重要思想,也是精华之一 @Aspect 这是一个切面的注解,声明是一个额外的面向切面的功能 ...
- Spring注解详解:@ComponentScan自动扫描组件使用
目录 无注解方式component-scan使用 注解方式@ComponentScan使用 @ComponentScan的扫描规则 无注解方式component-scan使用 之前,我们需要扫描工程下 ...
- @Configuration Spring注解详解
第一个作用 使用注释类@Configuration表示它的主要目的是作为bean定义的来源 第二个作用 @Configuration类允许通过简单地调用@Bean同一类中的其他方法来定义bean间依赖 ...
- spring注解详解,看完你就都全懂了!!
转载:https://blog.csdn.net/walkerjong/article/details/7946109
- Spring Boot注解详解
文章目录 使用注解的优势 注解详解(配备了完善的释义) 注解列表如下 JPA注解 springMVC相关注解 全局异常处理 项目中具体配置解析和使用环境 使用注解的优势 采用纯java代码,不在需要配 ...
最新文章
- smartsql和mysql_SmartSql 常见问题
- 牛客网 暑期ACM多校训练营(第一场)J.Different Integers-区间两侧不同数字的个数-离线树状数组 or 可持久化线段树(主席树)...
- iNeuOS云操作系统,.NET Core全系打造
- PHP操作Redis常用技巧
- WordPress: 通过数据库(phpMyAdmin)添加admin用户
- 这可能是你见过的最全的网络爬虫总结
- 外媒:欧盟针对谷歌语音助手展开反垄断调查
- c matlab 引擎调用,【MATLAB与C的混合编程】之【C程序调用Matlab计算引擎】(1)
- jieba(结巴)—— Python 中文分词
- css3 颜色 文本
- Atitit 导航模式 面包屑 胶囊式 标签式tab 目录 1.1. 表格导航	1 2. 面包屑导航来源于童话故事中的汉塞尔利用面包屑来记录回家的路的故事	1 2.1.1. 格林童话《Hanse
- 4. 两个排序数组的中位数
- sqlmap使用教程(超详细)
- Linux蓝牙耳机软件,Linux下蓝牙耳机的配置与测试
- CIM概念和总计架构
- ACM中AC、WA、PE、RE分别是什么意思
- Stata 中 profile.do 的设定
- UC 浏览器曝中间人攻击漏洞,官方:已修复,国内版不受影响
- 军犬舆情每日热点:强生爽身粉致癌案 被判赔偿47亿美元;华为正式进军电视行业
- Simulink选择器模块(Selector)
热门文章
- 儒家的礼与分配及社会契约
- 用spring.data的API,ElasticsearchRestTemplate来简单操作Elasticsearch的增删改查等功能~
- MFC Web浏览器
- vs2005无法附加,绑定句柄无效
- 读书系列----《别让情绪失控害了你》
- MSU2020年度世界视频编码大赛 金山云斩获UGC赛道冠军
- 【调剂】江西理工大学【地学大数据与人工智能团队】招地理信息、大数据、人工智能专业调剂生...
- Fluke 985粒子计数器是品质的保证
- xposed输出qq加密前明文数据
- E. Physical Education Lessons