博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring应用于组件注册的注解
阅读量:4073 次
发布时间:2019-05-25

本文共 6848 字,大约阅读时间需要 22 分钟。

在将Spring框架应用于项目开发中时,繁多的xml配置文件会使项目的维护升级变得困难,特别是项目很大时,有时候会花掉大量的时间去定位相应的组件配置。为了解决这个问题,引入Spring框架中的强大注解变得很重要,同时,注解的学习更是为后期学习Spring Boot做好了铺垫。

@Configuration

@Configuration注解用于定义配置类,并用于构建bean定义,初始化Spring容器,被标注的类类似于Spring的xml配置文件中的beans标签。

@Bean

给容器注册一个Bean;类型为方法返回值类型,id不指定时默认使用方法名作为id。

@ComponentScan

配置自动扫描相应的包。会自动扫描包路径下面的所有标注了@Controller、@Service、@Repository、@Component 的类。包含的属性如下:

  • value:指定扫描的包路径。接收String数组。
  • @Filter:声明扫描包的过滤规则,可以按注解、类型、正则表达式等进行过滤。

@ComponentScans

如果是JDK8以上可以声明多个@ComponentScan进行配置,也可以在@ComponentScans中配置多个@ComponentScan。

//配置类==配置文件@Configuration //告诉spring这是一个配置文件@ComponentScan(value="com.jt",/*excludeFilters*/ includeFilters = {        @Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})},useDefaultFilters=false)//配置自动扫描相应的包/*@ComponentScans(value = {        @ComponentScan(value="com.jt",excludeFilters  = {                @Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})})})*//**@ComponentScan vaue:指定要扫描的包 *excludeFilters = Filter[],指定扫描的时候按照什么规则排除哪些组件。 *includeFilters = Filter[],指定扫描的时候只包含哪些组件。生效的前提是让useDefaultFilters *FilterType.ANNOTATION 按照注解 *FilterType.ASSIGNABLE_TYPE 按照给定的类型 *FilterType.ASPECTJ 使用ASPECTJ表达式 *FilterType.REGEX 使用正则表达式 *FilterType.CUSTOM 使用自定义规则(需要实现TypeFilter接口) *  */public class MainConfig {
//给容器注册一个Bean;类型为返回值类型,id不指定时默认使用方法名作为id @Bean("person1") public Person person(){ return new Person("lishi",20); }}

@Scope

控制Bean的作用范围。

@Lazy

懒加载。

/**默认是单实例的     * prototype:多实例:ioc容器启动时并不会去调用方法创建对象,     *                 而是每次获取的时候才调用方法去创建对象。     * singleton:单实例(默认值):ioc容器启动时会调用方法创建对象并放入容器中。     *                                                  以后每次获取是直接从容器(map.get())中获取。     * request:同一次请求创建一个实例     * session:同一个session创建一个实例     *      *      * 懒加载:对于单实例的Bean,默认容器启动的时候创建对象;     *       懒加载就是容器启动的时候不创建对象,而是第一次获取(map.get())对象时才初始化对象。     * */    @Scope("prototype")    @Lazy    @Bean("person")    public Person person(){        System.out.println("获取Person....");        return new Person("张三",25);    }

@Conditional(条件注解)

标注在方法上时,按照一定的条件进行动态转配,满足条件才给容器中注册Bean。标注在配置类上时,满足当前条件,这个类配置中的所有Bean才能生效。其中这个条件类必须实现Condition接口。

/**     * @Conditional({Condition}):按照一定的条件进行动态转配,满足条件才给容器中注册Bean     *      * 如果系统是Windows,给容器中注册bill     * 如果系统是Linux,给容器中注册Linus     *      * */    @Conditional({WindowsCondition.class})    @Bean("bill")    public Person person01(){        return new Person("Bill Gates",60);    }    @Conditional({LinuxCondition.class})    @Bean("linus")    public Person person02(){        return new Person("linus",40);    }
//判断对象是否是linuxpublic class LinuxCondition implements Condition{
/** * ConditionContext:判断条件能使用的上下文(环境) * AnnotatedTypeMetadata:标注了@Conditional的注释信息 * */ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //判断是否Linux系统 //常用方法 //1、能获得IOC使用的BeanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //2、能获取到类加载器 ClassLoader classLoader = context.getClassLoader(); //3、获取当前环境信息 Environment environment = context.getEnvironment(); //4、获取到Bean定义的注册类 BeanDefinitionRegistry registry = context.getRegistry(); //判断容器中Bean的注册情况,也可以给容器注册Bean boolean difinition = registry.containsBeanDefinition("person"); String property = environment.getProperty("os.name"); if(property.contains("linux")){ return true; } return false; }}
//判断系统是否是windowspublic class WindowsCondition implements Condition{
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 判断是否Windows Environment environment = context.getEnvironment(); String property = environment.getProperty("os.name"); if(property.contains("Windows")){ return true; } return false; }}
@Import

快速给容器中注册组件。id默认是全类名。

@Import({Color.class})//@Import导入组件,id默认是组件的全类名public class MainConfig2 {    //...}
  • ImportSelector:如果某个类实现了ImportSelector接口,通过重写接口中的方法selectImports,可以将需要注册的类的全类名返回给@Import注解,并实现批量注册。
@Import({MyImportSelector.class})//@Import导入组件,id默认是组件的全类名public class MainConfig2 {    //.....}
//自定义逻辑返回需要导入的组件public class MyImportSelector implements ImportSelector{
//返回值就是要注册到容器中的组件 //AnnotationMetadata:当前标注@Import注解的类的所有注解信息 public String[] selectImports(AnnotationMetadata importingClassMetadata) { // TODO Auto-generated method stub //可以返回空数组,但是不能是null,否则会包空指针异常。 return new String[]{
"com.jt.bean.Color","com.jt.bean.Red"}; }}
  • ImportBeanDefinitionRegistrar:手动注册Bean到容器中。
@Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})//@Import导入组件,id默认是组件的全类名public class MainConfig2 {    //...}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/** * AnnotationMetadata:当前类的注解信息 * BeanDefinitionRegistry:BeanDefinition注册类; * 把所有需要添加到容器中的Bean,调用 * BeanDefinitionRegistry.registerBeanDefinition手工注册进容器 * */ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //定义注册Bean的条件 boolean difinition = registry.containsBeanDefinition("com.jt.bean.Red"); if(difinition){ //指定Bean的定义信息(Bean的类型,Bean的作用域...) RootBeanDefinition paramBeanDefinition = new RootBeanDefinition(RainBow.class); //注册一个bean,指定bean的别名 registry.registerBeanDefinition("com.jt.bean.RainBow", paramBeanDefinition); } }}

使用FactoryBean注册组件

Spring提供了一个org.Springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。

@Beanpublic ColorFactoryBean colorFactoryBean(){    return new ColorFactoryBean();}
//创建一个Spring定义的FactoryBeanpublic class ColorFactoryBean implements FactoryBean
{
//返回一个Color对象,这个对象会注册到容器中public Color getObject() throws Exception { // TODO Auto-generated method stub System.out.println("ColorFactoryBean...getObject()..."); return new Color();}public Class
getObjectType() { // TODO Auto-generated method stub return Color.class;}//是否单实例//true:这个bean是单实例,在容器中保存一份//false:多实例,每次获取都会创建一个新的beanpublic boolean isSingleton() { // TODO Auto-generated method stub return true;}}
@Testpublic void testImport(){    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);    printBeans(applicationContext);    //工厂Bean获取到的是调用getObject()创建的对象    Object object = applicationContext.getBean("colorFactoryBean");    Object object2 = applicationContext.getBean("colorFactoryBean");    System.out.println(object);    System.out.println(object == object2);    //获取colorFactoryBean本身时添加一个&符号    Object object3 = applicationContext.getBean("&colorFactoryBean");    System.out.println(object3);}

转载地址:http://kbkni.baihongyu.com/

你可能感兴趣的文章
Tensorflow入门资料
查看>>
剑指_用两个栈实现队列
查看>>
剑指_顺时针打印矩阵
查看>>
剑指_栈的压入弹出序列
查看>>
剑指_复杂链表的复制
查看>>
服务器普通用户(非管理员账户)在自己目录下安装TensorFlow
查看>>
星环后台研发实习面经
查看>>
大数相乘不能用自带大数类型
查看>>
字节跳动后端开发一面
查看>>
CentOS Tensorflow 基础环境配置
查看>>
centOS7安装FTP
查看>>
FTP的命令
查看>>
CentOS操作系统下安装yum的方法
查看>>
ping 报name or service not known
查看>>
FTP 常见问题
查看>>
zookeeper单机集群安装
查看>>
do_generic_file_read()函数
查看>>
Python学习笔记之数据类型
查看>>
Python学习笔记之特点
查看>>
shell 快捷键
查看>>