Spring实战(第四版) 第三章 高级装配

1、环境与Profile

配置profile bean

  • 首先要将所有不同的bean定义整理到一个或多个profile之中,在将应用部署到每个环境时,要确保对应的profile处于激活状态
  • @Profile,指定某个bean属于哪一个profile @Profile("dev")

激活profile

有两个属性:spring.profiles.active spring.profiles.default

2、条件化bean

根据条件才创建bean @Conditional注解

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MagicConfig {

  @Bean
  @Conditional(MagicExistsCondition.class)
  public MagicBean magicBean() {
    return new MagicBean();
  }
  
}
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 MagicExistsCondition implements Condition {

  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return env.containsProperty("magic");
  }
  
}
  • ConditionContext接口

    • getRegistry() 可检查bean定义
    • getBeanFactory() 可检查bean是否存在、探查bean属性
    • getEnviroment() 可检查环境变量是否存在以及它的值
    • getResourceLoader() 返回ResourceLoader加载的资源(比如磁盘资源)
    • getClassLoader() 检查类是否存在
  • AnnotatedTypeMetadata接口

    • isAnnotated() 判断带有@Bean注解的方法是不是还有其他注解
    • getAnnotationAttributes()
    • getAllAnnotationAttributes()

3、处理自动装配的歧义性

处理有多个可供装配的对象的情况

首选bean

  • @Primary标签
@Component
@Primary
public class IceCream implements Dessert {}

限定自动装配的bean

  • @Qualifier注解,设置的参数就是想要注入的bean的ID。
@Component
@Qualifier("cold")
public class IceCream implements Dessert {}

@Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert) {
  this.dessert = dessert;
}
  • 不允许在同一个条目上重复出现相同类型的多个注解,也可以自己创建标签进行注解
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.Type})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold {}

4、bean的作用域

默认情况下,Spring应用上下文所有bean都是作为以单例的形式创建的。不管给定一个bean被注入多少次,每次注入的都是同一个实例。

  • 单例:在整个应用中,只创建bean的一个实例。
  • 原型:每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
  • 会话:在Web应用中,为每个会话创建一个bean实例。
  • 请求:在Web应用中,为每个请求创建一个bean实例。
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad {}

使用会话和请求作用域

  • 如果有个购物车类,需要为每个用户都生成一个实例,同时有一个商店类,会为购物车提供相关服务。
  • 但是商店类是单例生成的,在Spring应用上下文加载时创建,而购物车类不是,这时会创建一个代理,注入到商店类里。
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart() {}

@Component
public calss StoreService {
  @Autowired
  public void setShoppingCart(ShoppingCart shoppingCart) {
    this.shoppingCart = shoppingCart;
  }
}

5、运行时值注入

注入外部值

  • @PropertySource注解,引入外部文件,从Environment实例中可以获取外部文件中的配置
  • 使用${...}引入外部信息
public class BlankDisc(@Value("$disc.title") String title, @Value("${disc.artist}") String artist) {
  this.title = title;
  this.artist = artist;
}

使用Spring表达式语言进行装配

  • 使用bean的ID来引用bean
  • 调用方法和访问对象的属性
  • 对值进行算是、关系和逻辑运算
  • 正则表达式匹配
  • 集合操作

使用方法是 #{}

  • #
  • #
  • #
  • #
  • #
  • #
  • #

posted on 2021-12-12 17:40  kaiker  阅读(8)  评论(0)    收藏  举报