Spring高级装配

spring高级装配

  • profile
    • 使用背景:当程序在不同的开发阶段,要用到不同的开发配置时,需要用到不同的bean,这个时候就需要profile来规定运行时需要哪个bean
    • 使用场景:在运行的时候根据环境确定创建哪个bean和不创建哪个bean
    • 使用方法:将某个bean定义整理到一个或者多个profile中,部署的时候确保相应的profile处于激活状态。
    • 配置profile bean
      • 可以用@Profile指定某个bean属于哪个profile
        • 示例

          40705d85-14a2-4a27-a147-40232039e9e9-1021317.jpg

        • 只有在dev profile激活时才会创建这个bean
        • 注1:注解开发profile@Profile作用在了类上,告诉Spring这个配置类中的bean只有在dev profile激活时才创建 dev profile没有被激活的话,@Bean的注解都会被忽略掉
        • 注2:Spring3.1中,只能在类级别上使用@Profile注解,在Spring3.2开始,你也可以在方法级别上使用@Profile注解,与@Bean注解一同使用,这样的话就能将两个bean放置到同一个配置类中。 尽管只有当规定的profile被激活时,相应的bean才会被创建,但是可能会有其他的bean并没有声明在一个给定的profile中。没有指定profile的bean始终都会被创建,与激活哪个profile没有关系。

          e98e777b-03a7-4e1a-87d9-d66b28379158-1021317.jpg

      • 在xml中配置profile
        • 第一种方法:为每一个profile配置一个xml文件,不提倡的做法
          • 示例:

            fcef27ad-8f3c-4724-8952-a12c99813a3c-1021317.jpg

        • 第二种方法:将所有的profile都放在同一个xml中
          • 示例如下:

            91803cea-34f3-48d8-90b9-7145d5a14a93-1021317.jpg

          • 注:两个bean的id都一样在创建的时候只会创建一个看激活哪一个。
    • 激活profile
      • 注意两个独立的属性
        • spring.profiles.active
          • 用来设置激活那个profile bean
        • spring.profiles.default
          • 当没有设置spring.profiles.active的时候会查找这个值,确定激活
        • 注:当两个值都没有设定的时候,只会创建普通的bean
      • 激活方法
        • a.作为DispatcherServlet的初始化参数
        • b.作为Web应用的上下文参数(web.xml)
          • 注:比较实用,用来配置所有的默认情况下的profile bean方便开发人员应用,在测试或部署的时候只需要激活响应的bean就可以。激活多个中间用,隔开。
          • 实例:

            89f88d6f-2c1b-4ba3-a4b1-9aa33c9b02fd-1021317.jpg

        • c.作为JNDI条目
        • d.作为环境变量
        • e.作为JVM的系统属性
        • f.在集成测试类上,使用@ActiveProfiles注解设置
          • 实例:

            92f85d7e-6e7e-4015-9e43-39d4b37f10ce-1021317.jpg

  • 条件化bean
    • 应用场景
      • 希望一个或者多个bean在应用的类库下包含特定的库时创建,或希望在某个bean也声明了之后才创建。
    • 实现方法
      • 用注解@conditional,可以用在带@bean的方法上
      • 给定条件计算结果为true时创建bean,否则不创建
      • 实例:
        • 配置bean

          d5efbb6a-86e2-4cee-9ad7-8da63c3f9156-1021317.jpg

        • 设置给conditional的类需实现condition接口,即参与判定的类必须实现condition接口

          fd76eab3-1c51-4ce8-8a29-d8f08ebb7e7b-1021317.jpg

      • matches方法的两个重要参数
        • ConditionContext功能如下
          • 借助getRegistry()返回的BeanDefinitionRegistry检查bean定义;
          • 借助getBeanFactory()返回的ConfigurableListableBeanFactory 检查bean是否存在,甚至探查bean的属性;
          • 借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么;
          • 读取并探查getResourceLoader()返回的ResourcesLoader 所加载的资源;
          • 借助getClassLoader()返回的ClassLoader加载并检查类是否存在。
        • AnnotatedTypeMetadata功能
          • 检测带有@Bean的方法上还有什么其他的注释
          • AnnotatedTypeMetadata也是一个接口

            19bd15eb-271e-41f3-8415-e120c32d8842-1021317.jpg

    • 从spring4开始@profile注解进行了重构,基于@conditional和condition实现
      • 实现@profile

        6910361c-c59b-4015-8203-b68866c2c5c6-1021317.jpg

      • ProfileCondition的实现

        676dda3b-e5ea-4543-87fe-65c0a9d0d5e3-1021317.jpg

      • 处理@profile的流程
        • 我们可以看到,ProfileCondition通过AnnotatedTypeMetadata得到了用于@Profile注解的所有属性。借助该信息,他会明确地检查value属性,该属性包含了bean的profile名称。然后根据ConditionContext得到的Environment来检查【借助acceptsProfiles()方法】该profile是否处于激活状态。
  • 处理自动装配的歧义性
    • 应用场景
      • 自动依赖注入的时候,依赖的是一个接口实现类的对象,这个接口可能拥有多个实现类,并且这些实现类都已经实例化为bean,这个时候spring就不能选择要注入哪一个bean,因此出现了注入歧义
    • 解决方法
      • 表示首选bean
        • 使用默认的限定标识符(默认的标识符为bean的ID)
          • 用@Primary
            • 使用自动装配

              af00bb9e-8aa8-4aef-aa50-7f46639b66cd-1021317.jpg

            • 使用java配置

              069cb9c3-08e3-48a9-bad6-b22f5fb1127e-1021317.jpg

            • 只用xml

              05b30f61-2561-4a1b-b33e-65ec5aad1339-1021317.jpg

          • 缺陷
            • 当两个或两个以上的bean被标记为首选,出现歧义的时候就不能正确的判断。
      • 限定自动装配的bean
        • 创建自定义的限定符
          • 使用默认的限定符,默认的限定符是bean的ID
            • 方法

              d3931d39-8373-4e4c-aeee-83e5973bd095-1021317.jpg

            • 缺点:当代码重构后,换了类名,就找不到相应的bean
          • 创建自定义的限定符
            • 创建

              3d9a2026-0423-4e83-8ec3-35aff257e054-1021317.jpg

            • 使用

              bfbc7569-948a-4179-8167-bb8d930d5e13-1021317.jpg

              116f9512-d958-4c35-8a0a-335332d1e655-1021317.jpg

        • 使用自定义的限定符注解
          • 使用场景
            • 当多个bean有相同的特性,即拥有相同的限定符。spring不允许叠加多个@Qualifier(" ").因为注解本身没有带有@Repeatable注解
          • 创建自定义的限定符注解

            6d1cdcdc-ed5c-429b-a422-e2466eea52f0-1021317.jpg

          • 使用自定义的限定符注解,在注入的时候应用相应的注解准确注入

            0b8de64f-5b3a-47b6-8d45-6f0f2bf9a67e-1021317.jpg

          • 自定义注解的方法就是:将已有的注解进行组合,如上面定义自定义的限定符注解一样
  • bean的作用域
    • 单例(singleton):
      • 在整个应用中,只创建bean的一个实例
      • 是默认的作用域,所有的依赖都用的是一个bean,缺点是当bean变化时得不到原来的bean
    • 原型(prototype):
      • 每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例
      • 使用方法
        • 自动创建

          7950eb23-df82-42a7-ab6d-8d2464efed4e-1021317.jpg

        • java配置类

          5c16e662-b104-4665-9f29-c599563f82f1-1021317.jpg

        • xml

          d2dea46f-3496-450d-be95-9061ece5d70f-1021317.jpg

    • 会话(Session):在Web应用中,为每个会话创建一个bean实例
      • 使用场景
        • 网上商城项目中,购物车bean,既要保持相对的独立,又必须保持在一个会话中是同一个。
      • 使用方法
        • 方法一:

          6fe9c91a-aacf-4007-91cc-09f4b2fd7e23-1021317.jpg

        • 方法二:默认情况下是用CGLib创建目标类代理,可以使用第二张图的方法关闭

          57890a44-ff39-4de1-9b74-150122f27d15-1021317.jpg

          41f44ad5-f807-4749-8fa4-59e6b54bd6e9-1021317.jpg

      • 解释proxyMode
        • 理解:见名知意,是一个规定代理模型,解决将会话或者请求bean注入到单例bean中遇到的问题
        • 问题场景:当需要将会话或请求bean注入到单例bean中的时候,单例bean会在spring上下文加载的时候创建,并注入相应的依赖,但是请求和会话bean是在运行的时候才会创建的。并且注入的bean要是特定用户的会话bean。
        • 解决办法:spring会注入一个会话或请求bean的代理,当用户建立会话时,代理会对其进行依赖解析调用委托给挥霍啊作用域内真正的bean。
        • 注:这里ScopedProxyMode.INTERFACES表明代理要实现的是一个被确切bean实现了的接口,如果代理要实现的是一个具体的类,则必须是用CGLib来生成基于类的代理,并且将proxyMode设为ScopeProxyMode.TARGET_CLASS
    • 请求(Request):在Web应用中,为每个请求创建一个bean实例
  • 运行是值注入
    • 产生的原因
      • 避免硬编码
      • 方法一:属性占位符
      • 方法二:spring表达式语言(SpEL)
    • 注入外部的值
      • 方法步骤:声明属性源,通过spring的environment检索属性
        • 46a2f6de-d557-4058-a696-19120d236aec-1021317.jpg

      • 深入理解Environment,getProperty方法的四种变形
        • a、String getProperty(String key)
        • b、String getProperty(String key,String defaultValue)
          • 当属性不存在时使用默认值
        • c、T getProperty(String key,Class type)
          • 获取一个类对象,并非完全字面量
        • d、T getProperty(String key,Class type,T defaultValue)
        • e、String[] getActiveProfiles() :返回激活profile名称的数组
        • f、String[] getDefaultProfiles():返回默认profile名称的数组
        • g、boolean adcceptsProfiles(String...profiles):如果environment支持给定profile的话,就返回true
        • h、getRequiredProperty(String key):属性必须存在,不存在会报错
        • i、getPropertyAsClass():将属性解析为类
      • 解析属性占位符
        • 占位符
          • 将属性定义到外部的属性文件,用占位符值将其插入到spring bean中
          • ${....}
          • 使用前提
            • 配置PropertyPlaceholderConfigurer bean或PropertySourcesPlaceholderConfigurer bea(从3.1开始推荐使用)
            • 在java中配置
              • 9cd0ebba-a1fa-43cc-9c48-68116e96d103-1021317.jpg

            • 在xml中配置
              • 4ac15e89-8006-4a1f-9173-80c9d0fbc0f3-1021317.jpg

        • 实例应用xml
          • <bean id="sgtPeppers" class="soundsystem.BlankDisc" c:_title="${disc.title}" c:_artist="${disc.artist}" />
        • 使用组件扫描和自动装配,用@value注解
          • 9e5439cc-710a-4205-ba90-3d82928e0f35-1021317.jpg

      • 使用spring表达式语言进装配(SpEL)
        • 使用格式
          • #{........}
        • 用法功能
          • a、使用bean的ID来引用bean;
          • b、调用方法和访问对象的属性;
          • c、对值进行算数、关系和逻辑运算;
          • d、正则表达式匹配;
          • e、集合操作。
        • 特殊的运算符
          • “?.”比“.”更加强大,能够在调用前判断对象是否存在,不存在抛出异常
          • T():结果是一个class对象
            • 例:T(java.lang.Math).PI
          • ? :
            • 第一种用法,和普通的三元运算符一样
            • 第二种用法,判断是否为null,如果为null使用默认的值 #{disc.title ?: 'rettle and hum'} 如果前面的title不存才用后面的字符串替换
          • matches
            • 用法:计算给定的值是否与正则表达式匹配,返回true或false
            • 用例:#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-+\\.com]'}
          • 计算集合
            • [ ] 用来从集合或数组中按照索引获取元素
              • #{jukebox.songs[4].title}
              • #{'This is a test' [3]}
            • '.?[ ]' 用来查询,将匹配到的查询项放到一个集合中
              • #{jukebox.songs.?[artist eq 'Aeronsmith']}
            • '.^[ ] '和'.$[ ]'用来在集合中查询第一个匹配项和最后一个匹配项
            • '.![ ]' 用来从集合的每一个成员中选择特定的属性放到另一个集合中,即抽取特定值,查看集合中存储的类型都有哪些

转载于:https://my.oschina.net/u/3942106/blog/1934620

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值