概述
- @Configuration
- @Bean
//@Bean//给容器注入一个bean,类型为返回值的类型,id默认方法名就是id @Bean("person")//指定id为person public Person person(){ return new Person("李四",12); }
<!-- 该注解对应的xml实现方式 --> <bean id="persion" class="indi.com.bean.Person"> <property name="name" value="张三"></property> <property name="age" value="18"></property> </bean>
- 默认是单例的
- 设置为多实例:@Scope
- @Scope
//@Bean//给容器注入一个bean,类型为返回值的类型,id默认方法名就是id @Scop("prototype") @Bean("person")//指定id为person public Person person(){ return new Person("李四",12); }
<!-- 该注解对应的xml实现方式 --> <bean id="persion" class="indi.com.bean.Person" scope="prototype"> <property name="name" value="张三"></property> <property name="age" value="18"></property> </bean>
- singleton:单实例(默认):IOC容器启动器会调用方法创建对象放到IOC容器中,以后每次使用时都直接从容器(map.get())中拿。
- prototype:多实例:IOC容器启动器时并不会调用方法创建对象放到容器中,每次获取时才会调用方法创建对象,每次获取都会调用方法创建对象。
- request:同一次请求创建一个实例
- session:同一个session创建一个实例
- @Lazy:针对单实例bean
- 单实例bean:默认容器加载时创建对象
- 使用@Lazy:容器加载时不创建对象,第一次使用(获取)bean对象时创建对象并初始化
@Lazy @Bean("person")//指定id为person public Person person(){ return new Person("李四",12); }
- @Conditional:
- 按照一定的条件判断,满足条件时给容器注册bean
- 可以放在方法上,也可以放在类上(类中组件统一设置)
- 使用方法:
- 写Condition的实现类
package indi.com.config; 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.type.AnnotatedTypeMetadata; public class LinuxCondition implements Condition { /** * * @param conditionContext:判断条件使用的上下文(环境) * @param annotatedTypeMetadata:注释信息 * @return */ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //获取IOC使用的beanFactory ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); //获取类加载器 ClassLoader classLoader = conditionContext.getClassLoader(); //获取当前环境 Environment environment = conditionContext.getEnvironment(); //获取bean定义的注册类 BeanDefinitionRegistry registry = conditionContext.getRegistry(); //容器中bean的注册情况 boolean person = registry.containsBeanDefinition("person"); //获取系统信息 String property = environment.getProperty("os.name"); if(property.contains("linux")){ return true; } return false; } }
-
注解
package indi.com.config; import indi.com.bean.Person; import org.springframework.context.annotation.*; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service; @Configuration @ComponentScan(value="indi.com") public class BeanConfig { @Conditional({LinuxCondition.class}) @Bean("linux") public Person linux(){ return new Person("linux",55); } }
- 写Condition的实现类
- @ComponentScan
- value:指定要扫描的包
@ComponentScan(value="indi.com")
<!-- 该注解对应的xml实现方式 --> <context:component-scan base-package="indi.com"></context:component-scan>
- excludeFilters = Filter[]:扫描时排除指定的组件
@ComponentScan(value="indi.com",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})})
- includeFilters=Filter[]:扫描时只需要包含指定的组件
- 需要禁用默认的扫描规则:userDefaultFilters=false;
@ComponentScan(value="indi.com",includeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,classes ={Controller.class})},useDefaultFilters = false)})
<!-- 该注解对应的xml实现方式 --> <context:component-scan base-package="indi.com" use-default-filters="false"></context:component-scan>
- 需要禁用默认的扫描规则:userDefaultFilters=false;
- @Filter
- type
- FilterType.ANNOTATION:按照注解
type=FilterType.ANNOTATION
- FilterType.ASSIGNABLE_TYPE:按照给定的类型
type=FilterType.ASSIGNABLE_TYPE
- FilterType.ASPECTJ:按照ASPECTJ表达式
- FilterType.REGEX:按照正则
- FilterType.CUSTOM:自定义规则
- 写一个TypeFilter的实现类:MyTypeFilter
package indi.com.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 { /** * * @param metadataReader:读取当前正在扫描的类的信息 * @param metadataReaderFactory:可以获取其他任何类的信息 * @return * @throws IOException */ 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")){ return true; } return false; } }
- 配置
@ComponentScan(value="indi.com",@Filter(type=FilterType.CUSTOM,class={MyTypeFilter}))
- 注意:根据MyTypeFilter的规则可知,在indi.com包下,所有类名中包含"er"的类(无论该类上是否有注解)都能扫描到
- 写一个TypeFilter的实现类:MyTypeFilter
- FilterType.ANNOTATION:按照注解
- type
- value:指定要扫描的包
- @ComponentScans
- @Import
- 方式一:
//id默认是组件的全类名 @Import(类名.class)或者@Import({类名1.class,类名2.class})
- 方式二:
- 写一个类实现ImportSelector
package indi.com.config; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; //自定义逻辑返回需要导入的组件 public class MyImportSelector implements ImportSelector { /** * * @param annotationMetadata:当前标注@Import注解的类的所有注解信息 * @return:导入到容器中的组件全类名 */ public String[] selectImports(AnnotationMetadata annotationMetadata) { //return new String[0];//默认 return new String[]{类1的全路径,类2的全路径}; } }
- 配置
//id默认是组件的全类名 @Import(类名.class)或者@Import({类名1.class,类名2.class,MyImportSelector.class})
- 写一个类实现ImportSelector
- 方式三:
- 写一个类实现ImportBeanDefinitionRegistrar
package indi.com.config; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param annotationMetadata:当前类的注解信息 * @param beanDefinitionRegistry:beanDefinition注册类 * 将所有需要添加到容器中的bean, * 通过beanDefinitionRegistry.registerBeanDefinition手工注册进来 */ public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { boolean test = beanDefinitionRegistry.containsBeanDefinition("类的全路径"); if(test){ RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(类.class); beanDefinitionRegistry.registerBeanDefinition("test",rootBeanDefinition); } } }
- 配置
//id默认是组件的全类名 @Import(类名.class)或者@Import({类名1.class,类名2.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
- 写一个类实现ImportBeanDefinitionRegistrar
- 方式一:
- FactoryBean(工厂Bean)
- 创建Spring定义的FactoryBean,实现FactoryBean
- 将创建的FactoryBean加入容器中
- 注意:工厂Bean获取的是调用getObject创建的对象
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(); Object bean = applicationContext.getBean("工具bean的注册ID");
- 获取工厂Bean本身:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(); Object bean = applicationContext.getBean("&工具bean的注册ID");
- 注意:工厂Bean获取的是调用getObject创建的对象
总结:给容器中注册组件
- 包扫描+组件标注注解(@Controller、@Service、@Repository、@Component)
- @Bean:导入第三方包里面的组件
- @Import:快速给容器中导入一个组件
- @Import(类名.class):容器中自动导入这个组件,id默认为全类名
- ImportSelector:返回需要导入的组件的全类名数组
- ImportBeanDefinitionRegistrar:手动注册bean到容器中
- 使用Spring提供的FactoryBean
- 默认获取的是工厂bean调用的getObject创建的对象
- 要获取工厂bean本身,需要给id前面加一个&
最后
以上就是眯眯眼长颈鹿为你收集整理的Spring注解(一):组件注册的全部内容,希望文章能够帮你解决Spring注解(一):组件注册所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复