上一节提到Spring之装配bean(一),我们已经了解到了装配的基础知识,这部分是更为高级的bean装配技术。

高级装配内容:

  • spring profile
  • 有条件的bean
  • 处理自动装配的歧义性
  • bean的作用域

1.spring profile

应用程序从一个环境迁移到另一个环境。开发阶段,某些环境相关做法可能并不适合迁移到生产环境中,甚至几遍迁移过去也无法正常工作,所以在不同的环境中使用的bean可能不同。下面以datasource为例:

在Java配置类中配置(“dev”和“prod”生产环境):

@Configuration
public class DataSourceConfig{@Bean(destroyMethod="shutdown")@Profile("dev")public DataSource dataSource(){return new EmbeddedDatabaseBuilder().addScript("classpath:schema.sqsl").addScript("classpath:test-data.sql").build();}@Bean@Profile("prod")public DataSource dataSource(){JndiObjectFactoryBean jndi=new JndiObjectFactoryBean();jndi.setJndiName("jdbc/myDS");jndi.setResourceRef(true);jndi.setProxyInterface(javax.sql.DataSource.class);return (DataSource) jndi.getObject();}
}

在xml中配置:

<beans xmlns="......."><beans profile="dev"><jdbc:embedded-database id="dataSource"><jdbc:script location="classpath:schema.sql" /><jdbc:script location="classpath:test-data.sql" /></jdbc:embedded-database></beans><beans profile="qa"><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destory-method="close"p:url="jdbc:h2:tcp://dbserver/~/test".......p:maxActive="30"/></beans>
</beans>

激活(使用)哪一个profile:

<!--为应用山下文设置默认的profile-->
<context-param><param-name>spring.profiles.default</param-name><param-name>dev</param-name>
</context-param>
<!--为Servlet设置默认的profile-->
<servlet><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>spring.profiles.default</param-name><param-value>dev</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>

2.有条件的bean

假设你希望一个或多个bean只有在应用的类路径下包含特定的库时才创建。或者我们希望某个bean只有当另外某个特定的bean也声明了之后才会创建。我们还可能要求只有某个特定的环境变量设置之后才会创建某个bean。在Spring4之前,很难实现这种级别的条件化配置,但是Spring4引入了一个新的@Conditioinal注解,他可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean就会被忽略。
有条件的bean一般在java配置注入bean的方法中使用到。

@Configuration
public class ConditionalConfig {@Bean@Conditional(MagicExistsConditional.class) //条件化的创建beanpublic MagicBean magicBean() {return new MagicBean();}
}
public class MagicExistsConditional implements Condition{@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Environment evn = context.getEnvironment();return evn.containsProperty("magic");}}

如你所见,设置给@Conditional的类可以是任意实现了Condition接口的的类型。而实现这个接口只需要实现matches方法,如果matches方法返回true就创建该bean,如果返回false则不创建bean,上例中我们就是根据环境变量中是否存在magic变量,来决定matches的返回值,进而决定是否创建MagicBean的。

但是在实际生产中,ConditionContext context, AnnotatedTypeMetadata metadata这两个参数可以对类中的其他信息进行判断,有兴趣可以查一下这两个类的api。

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

如果不仅有一个bean能够匹配结果的话,这种歧义性阻碍Spring自动装配属性、构造器参数或方法参数。 下面是一个例子:

@Autowired
public void setDessert(Dessert dessert){this.dessert = dessert;
}
@Component
public class Cake implements Dessert{...}
@Component
public class Cookies implements Dessert{...}
@Component
public class IceCream implements Dessert{...}

在这里,当Spring试图自动装配setDessert()中的Dessert参数时,它并没有唯一、无歧义的可选值。因而,Spring会抛出NoUniqueBeanDefinitionException;

解决方案1:将其中一个bean设置为首选

@Component
@Primary
public class Cake implements Dessert{...}

或者在xml中

<bean id = "iceCream"
class = "com.desserteater.Icecream"
primary = "true">
</bean>

解决方法2:使用限定符(qualifier)来帮助Spring将可选的bean的范围缩小

@Autowired
@Qualifier("cake")
public void setDessert(Dessert dessert){this.dessert = dessert;
}

4、bean的作用域

  • 单例(singleton):在整个应用中,只创建bean的一个实例。
  • 原型(prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
  • 会话(Session):在Web应用中,为每个会话创建一个bean实例。
  • 请求(Request):在Web应用中,为每个请求创建一个bean实例。

单例是默认的作用域,但是正如之前所述,对于易变的类型,这并不合适。如果选择其他的作用域,要使用@Scope注解,他可以与@Component(自动装配)或@Bean(JavaConfig)一起使用。

例如,如果你使用组件扫描来发现声明bean,那么你可以在bean的类上使用@Scope注解,将其声明为原型bean,如下:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//@Scope("prototype")
public class Notepad{...}

或者

<bean id="notepad"class="com.myapp.Notepad"scope="prototype"  />

使用会话和请求作用域

@Component
@Scope(value=WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart(){...}

这里,我们将value设置成了WebApplicationContext中的SCOPE_SESSION常量(它的值是session)。这会告诉Spring为Web应用中的每个会话创建一个ShoppingCart。这会创建多个ShoppingCart bean 实例,但是对于给定的会话只会创建一个实例,在当前会话相关的操作中,这个bean实际上相当于单例。
@Scope同时还有一个proxyMode属性,它被设置成了ScopedProxyMode.INTERFACES。这个属性解决了将会话或请求作用域的bean注入到单例bean中所遇到的问题。作用域代理能够延迟注入请求和会话作用域的bean。

在xml中注入:

<bean id="cart"class="com.myapp.ShoppingCart"scope="session"><aop:scoped-proxy />
</bean>

Spring之高级装配(二)相关推荐

  1. spring(3)高级装配

    [0]README 0)本文部分文字描述转自:"Spring In Action(中/英文版)",旨在review  spring(3)高级装配 的相关知识: [1]环境与prof ...

  2. 《Spring实战》读书笔记-第3章 高级装配

    <Spring实战>是学习Spring框架的一本非常经典的书籍,之前阅读了这本书,只是在书本上写写画画,最近整理了一下<Spring实战>的读书笔记,通过博客的方式进行记录分享 ...

  3. 《Spring实战》读书笔记-第3章 高级装配,zookeeper原理图

    文章目录 3.1 环境与profile 3.2 条件化的bean 3.3 处理自动装配的歧义性 3.4 Bean的作用域 3.5 运行时植注入 3.6 小结 本章内容: Spring profile ...

  4. 《Spring实战》读书笔记-第3章 高级装配,字节跳动四面技术面

    当自动装配bean时,遇到多个实现类的情况下,就出现了歧义,例如: @Autowired public void setDessert(Dessert dessert) { this.dessert ...

  5. 《Spring实战》读书笔记-第3章 高级装配,最新Java大厂高频面试题

    <jee:jndi-lookup id="dataSource" lazy-init="true" jndi-name="jdbc/myData ...

  6. spring面试题(二)

    目录 硅谷 一 .请写出 spring 中常用的依赖注入方式. 二  .简述Spring中IOC容器常用的接口和具体的实现类 三 .简述Spring中如何基于注解配置Bean和装配Bean 四.  说 ...

  7. Spring Boot自动装配原理详解

    目录 1.环境和依赖 1.1.spring boot版本 1.2.依赖管理 2.自动装配 2.1.流程概述 2.2.三大步前的准备工作 2.2.1.注解入口 2.2.2.获取所有配置类 2.3.获取过 ...

  8. 【Spring】—— 自动装配

    一.Spring中装配bean的方式 1.在XML中显式配置 2.在Java中进行显式配置 3.隐士的bean发现机制和自动装配 二.自动装配示例 1.在需要装配到其他bean中的类中加入@Compo ...

  9. spring Bean自动装配

    spring Bean自动装配 自动装配是使用spring满足bean依赖的一种方式. spring会在应用上下文中为某个bean寻找其依赖的bean. spring自动装配需要从两个角度来实现,或者 ...

最新文章

  1. php 语句插入失败,php – Mysqli准备语句插入不插入
  2. PHP学习笔记-PHP与JavaScript的交互
  3. vue案例-计数器.html
  4. 扩散(洛谷-P1661)
  5. ASP.NET实现多域名多网站共享Session值
  6. Struts2教程3:struts.xml常用配置解析
  7. 小程序 · 云开发快速入门与实战
  8. Wiki系列(一):Wiki系统选择
  9. android 清理系统垃圾,安卓手机清理系统垃圾方法汇总
  10. 计算机软件工程学校排名,软件工程专业全国高校排名前十
  11. 237. 删除链表中的节点 (Delete Node in a Linked List)
  12. 原来 Elasticsearch 还可以这么理解
  13. 关于vue组件引用外部Js数值和方法出现的问题
  14. 谈谈Python的Flask框架学习与福利分享
  15. 计算机网络超时重传时间,TCP超时重传机制
  16. 条码打印软件引用其他对象内容的方法
  17. 小学教师计算机校本培训计划,中小学教师信息技术应用校本培训方案
  18. 【pycharm环境搭建(python脚本编辑器)】
  19. 【梦幻连连连】源码分析(二)
  20. UVA - 1640 The Counting Problem (数位dp)

热门文章

  1. shell脚本报错:-bash: xxx: /bin/sh^M: bad interpreter: No such file or directory
  2. VS2008部分使用技巧
  3. TCP的拥塞控制--慢启动,拥塞避免,快重传,快速恢复
  4. 最强新一代消息系统,没有之一,不接受反驳!
  5. 基于LZ77算法的文件压缩
  6. LiveVideoStackCon 2022 上海站 专题抢先看(4)
  7. 高性能视频推理引擎优化技术
  8. BBR及其在实时音视频领域的应用
  9. 1.65亿人次扫码登记的背后,是TBase的秒级返回
  10. 1024程序猿节:揭秘腾讯老中青三代程序猿工位