码迷,mamicode.com
首页 > 编程语言 > 详细

关于@Profile、@Conditional、@Primary、@Qualifier及@Scope等实现高级装配的spring注解

时间:2018-10-16 13:43:07      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:3.2   test   就是   忽略   active   引用   关于   相关   span   

1、关于@Profile注解的介绍

@Profile注解主要用在针对不同环境而条件选择的注入bean

在开发过程中由于环境的不同,我们可能在针对某些功能,需要开发不同的实现,然而在某种环境中,只能激活其中一种实现,其他的实现处于不激活的状态。这个时候我们在需要创建的bean上添加@Profile注解,如@Profile("dev"),"dev"是激活的标识。当此没有注解被激活时,该注解下的所有@Bean都会被忽略掉,激活则相反。@Profile注解在spring3.1只能在类级别上注解,spring3.2开始可以在方法级别注解。

如:

 @Profile("dev")
    public class TestProfile{
        
        @Bean
        public TofuCai setTofuCai(){
            return new TofuCai;
        }
     
    }


@profile的激活依赖两个独立的属性:spring.profiles.active和spring.profiles.default。

有多种方式来设置这两个属性

    作为DispatcherServlet的初始化参数;

    作为Web应用的上下文参数;

    作为JNDI的条目;

    作为环境变量;

    作为JVM的系统属性;

    在集成车市类上,使用@ActiveProfiles注解设置

如为上下文设置默认的profile:

<context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>dev</param-value>
  </context-param>


注意:可以同时激活多个profile,通过逗号分隔来实现

 
2、@Conditional条件化的bean

当我们需要将某个bean注入到Spring中时,需要考虑到,这个bean只有在满足某些条件才去创建时,这个时候我们在这个bean的类或法返回对象的方法上,添加@Conditional注解。

例如:

    @Bean
    @Conditional(TofuCaiCondition.class)
    public TofuCai tofuCaiBean(){
        return new TofuCai();
    }


我们在创建TofuCai这个Bean时,添加了创建的条件。

再添加这个注解后,我们需要实现Condition这个接口,只需提供matches的实现就好。

例如:

    public class TofuCaiCondition implements Condition{
        public boolean matches(
             ConditionContext context, AnnotatedTypeMetadata metadata){
            Environment env = context.getEnvironment();
            return env.containsProperty("tofu");    
        }
    }

其实@Profile的内部实现,也是使用了@Conditional这个注解

如下是spring 4中 @Profile的实现:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Documented
    @Conditional(ProfileCondition.class)
    public @interface Profilr{
        String[] value();
    }

3、@Qualifier 处理装配的歧义性

先解释下何为歧义性:当使用@Autowired或者其他注解(如:@Inject)进行装配的时候,由于该引用下存在多个实现,spring不知晓从众多实现中取其中的哪一个进行装配。这我们称之为歧义性。而@Qualifier则能很好解决装配的歧义性。

在这之前我先说下@Primary这个注解。

当我们在某个需要注入的bean使用这个注解的时候,当发生歧义性的时候,spring就会装配有@Primary这个实现。需要注意的是,在多个实现中,只能最多只有一个实现可以使用这个注解,否则还是会产生歧义性。

这个时候,就轮到@Qualifier这个注解大显身手了。

在装配的额外增加@Qualifier("tofu")这个注解,就意味着spring会直接寻找Tofu这个bean。当然你可以在注入这个bean指定下ID,同样加上@Qualifier这个注解。例如:

    @Component
    @Qualifier("cai")
    public class Tofu implement TofuCai{
        
    }

 注意:@Qualifier注解可以跟注入bean的注解一起使用,比如@Bean也是可以结合使用的,注意其不同组合之间的含义。在与注入bean的相关注解使用时,是代表限定符的意思,在装配的时候某种角度来说,是引用的指向的意思。

    @Autowired
    @Qualifier("cai")
    public void setTofuCai(TofuCai tofuCai){
        this.tofuCai = tofuCai;
    }

其实介绍到现在基本上已经很难再存在歧义性的问题了,但是有时候吧,有的人在注入bean的时候,限定符重复使用。这就导致在装配时,又出现歧义性。而且Java是不允许同一个条目上重复出现相同的注解。因此spring提供终极解决方案,即使用自定义的限定符注解,就是用户自己定义限定符注解,既可单个使用,也可组合使用。

例如:

    @Target({ElementType.CONSTRUCTOR,ElementType.FILED,
            ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public @interface Cai{}
   @Target({ElementType.CONSTRUCTOR,ElementType.FILED,
            ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public @interface Tofu{}

就分别定义了@Tofu和@Cai两个注解,直接在装配和注入的时候使用这两个注解就好了,而且既可以单独使用,也可以组合使用,不必考虑注解的重复。
4、@Scope注解——bean的作用域

先大致介绍下spring定义的一些作用域:

       单例(Singleton):在整个应用中,只创建bean的一个实例。

       原型(Prototype):每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean的实例。

       会话(Session):在Web应用中,为每个会话创建一个bean的实例。

       请求(Request):在Web应用中,为每个请求创建一个bean的实例。

在bean的类上使用@Scope注解,例如:

    @Component
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class TofuCai{...}

这里就将这TofuCai设置成原型作用域。

也可以这么使用@Scope("prototype"),但是没有使用SCOPE_PROTOTYPR更加安全,不易出错。

关于@Profile、@Conditional、@Primary、@Qualifier及@Scope等实现高级装配的spring注解

标签:3.2   test   就是   忽略   active   引用   关于   相关   span   

原文地址:https://www.cnblogs.com/TofuCai/p/9796999.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!