Spring应用于组件注册的注解

在将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);
    }
//判断对象是否是linux
public 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;
    }

}
//判断系统是否是windows
public 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的逻辑。

@Bean
public ColorFactoryBean colorFactoryBean(){
    return new ColorFactoryBean();
}
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color>{

//返回一个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:多实例,每次获取都会创建一个新的bean
public boolean isSingleton() {
    // TODO Auto-generated method stub
    return true;
}

}
@Test
public 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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值