spring实战(2)--高级装配
发布日期:2021-10-04 02:53:43 浏览次数:4 分类:技术文章

本文共 5181 字,大约阅读时间需要 17 分钟。

一、profile

1、@Profile:应用在类级别上告诉Spring这个配置类中的bean只有在此profile激活时才会创建。在Spring 3.1中,只能在类级别上使用@Profile注解。从Spring 3.2开始,你也可以在方法级别上使用@Profile注解,与@Bean注解一同使用。没有指定profile的bean始终都会被创建,与激活哪个profile没有关系。

2、xml中在中增加属性profile:在根元素中嵌套定义元素,而不是为每个环境都创建一个profile XML文件。这能够将所有的profile bean定义放到同一个XML文件中,同时增加该属性。

3、@ActiveProfiles:Spring提供了@ActiveProfiles注解,我们可以使用它来指定运行测试时要激活哪个profile。在集成测试时,通常想要激活的是开发环境的profile。

二、条件化的bean

1、@Conditional:Spring 4引入了一个新的@Conditional注解,它可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。 @Conditional将会通过Condition接口进行条件对比,设置给@Conditional的类可以是任意实现了Condition接口的类型。

三、自动装配歧义性

1、@Primary:在Spring中,可以通过@Primary来表达最喜欢的方案。@Primary能够与@Component组合用在组件扫描的bean上,也可以与@Bean组合用在Java配置的bean声明中。如果你使用XML配置bean的话,同样可以实现这样的功能。元素有一个primary属性用来指定首选的bean。只能标示一个优先的可选方案。

2、@Qualifier:Spring的限定符能够在所有可选的bean上进行缩小范围的操作,最终能够达到只有一个bean满足所规定的限制条件。@Qualifier是使用限定符的主要方式。它可以与@Autowired和@Inject协同使用,在注入的时候指定想要注入进去的是哪个bean。

3、创建自定义的限定符:可以为bean设置自己的限定符,而不是依赖于将bean ID作为限定符。在这里所需要做的就是在bean声明上添加@Qualifier注解。它可以与@Component组合使用。当通过Java配置显式定义bean的时候,@Qualifier也可以与@Bean注解一起使用。当使用自定义的@Qualifier值时,最佳实践是为bean选择特征性或描述性的术语,而不是使用随意的名字。

4、使用自定义的限定符注解:可以创建自定义的限定符注解,借助这样的注解来表达bean所希望限定的特性。这里所需要做的就是创建一个注解,它本身要使用@Qualifier注解来标注。这样我们将不再使用@Qualifier(“cold”),而是使用自定义的@Cold注解。通过在定义时添加@Qualifier注解,它们就具有了@Qualifier注解的特性。它们本身实际上就成为了限定符注解。通过声明自定义的限定符注解,我们可以同时使用多个限定符,不会再有Java编译器的限制或错误。与此同时,相对于使用原始的@Qualifier并借助String类型来指定限定符,自定义的注解也更为类型安全。

四、bean的作用域

1、Spring定义了多种作用域,可以基于这些作用域创建bean,包括:单例(Singleton):在整个应用中,只创建bean的一个实例。原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。会话(Session):在Web应用中,为每个会话创建一个bean实例。请求(Rquest):在Web应用中,为每个请求创建一个bean实例。

2、@Scope:单例是默认的作用域,但是正如之前所述,对于易变的类型,这并不合适。如果选择其他的作用域,要使用@Scope注解,它可以与@Component或@Bean一起使用。使用ConfigurableBeanFactory类的SCOPE_PROTOTYPE常量设置了原型作用域。

3、scope属性:如果你使用XML来配置bean的话,可以使用元素的scope属性来设置作用域。

4、会话作用域:就购物车bean来说,会话作用域是最为合适的,因为它与给定的用户关联性最大。要指定会话作用域,我们可以使用@Scope注解,它的使用方式与指定原型作用域是相同的。

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

(2)@Scope的proxyMode属性:被设置成了ScopedProxyMode.INTERFACES,这表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean。如果bean类型是具体类的话,我们必须要将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以此来表明要以生成目标类扩展的方式创建代理。请求作用域的bean会面临相同的装配问题。因此,请求作用域的bean应该也以作用域代理的方式进行注入。

5、XML来声明会话或请求作用域的bean:元素的scope属性能够设置bean的作用域,要设置代理模式,我们需要使用Spring aop命名空间的一个新元素。aop:scoped-proxy是与@Scope注解的proxyMode属性功能相同的Spring XML配置元素。它会告诉Spring为bean创建一个作用域代理。默认情况下,它会使用CGLib创建目标类的代理。但是我们也可以将proxy-target-class属性设置为false,进而要求它生成基于接口的代理。必须在XML配置中声明Spring的aop命名空间。

五、运行时值注入

1、值注入:依赖注入是将一个bean引用注入到另一个bean的属性或构造器参数中。它通常来讲指的是将一个对象与另一个对象进行关联。bean装配的另外一个方面指的是将一个值注入到bean的属性或者构造器参数中。硬编码是可以的,但有的时候,会希望避免硬编码值,而是想让这些值在运行时再确定。为了实现这些功能,Spring提供了两种在运行时求值的方式:

(1)属性占位符(Property placeholder)。

(2)Spring表达式语言(SpEL)。

2、@PropertySource:在Spring中,处理外部值的最简单方式就是声明属性源并通过Spring的Environment来检索属性。@PropertySource引用了类路径中一个名为app.properties的文件。这个属性文件会加载到Spring的Environment中,稍后可以从这里检索属性。

3、Spring的Environment:getProperty()方法并不是获取属性值的唯一方法,getProperty()方法有四个重载的变种形式。Environment还提供了几个与属性相关的方法,如果你在使用getProperty()方法的时候没有指定默认值,并且这个属性没有定义的话,获取到的值是null。如果你希望这个属性必须要定义,那么可以使用getRequiredProperty()方法。如果想检查一下某个属性是否存在的话,那么可以调用Environment的containsProperty()方法。如果想将属性解析为类的话,可以使用getPropertyAsClass()方法。除了属性相关的功能以外,Environment还提供了一些方法来检查哪些profile处于激活状态。

4、解析属性占位符:Spring一直支持将属性定义到外部的属性的文件中,并使用占位符值将其插入到Spring bean中。在Spring装配中,占位符的形式为使用“${ … }”包装的属性名称。如果我们依赖于组件扫描和自动装配来创建和初始化应用组件的话,那么就没有指定占位符的配置文件或类了。在这种情况下,我们可以使用@Value注解,它的使用方式与@Autowired注解非常相似。为了使用占位符,我们必须要配置一个PropertyPlaceholderConfigurer bean或PropertySourcesPlaceholderConfigurer bean。从Spring 3.1开始,推荐使用PropertySourcesPlaceholderConfigurer,因为它能够基于Spring Environment及其属性源来解析占位符。如果你想使用XML配置的话,Spring context命名空间中的context:propertyplaceholder元素将会为你生成PropertySourcesPlaceholderConfigurer bean。

5、使用Spring表达式语言进行装配:Spring 3引入了Spring表达式语言(Spring Expression Language,SpEL),它能够以一种强大和简洁的方式将值装配到bean属性和构造器参数中,在这个过程中所使用的表达式会在运行时计算得到值。SpEL拥有很多特性,包括:

(1)使用bean的ID来引用bean;

(2)调用方法和访问对象的属性;

(3)对值进行算术、关系和逻辑运算;

(4)正则表达式匹配;

(5)集合操作。

6、SpEL样例:

(1)SpEL表达式要放到“#{ … }”之中。T()表达式会将java.lang.System视为Java中对应的类型,因此可以调用其static修饰的currentTimeMillis()方法。

(2)在bean装配的时候使用这些表达式。可以使用@Value注解,这与之前看到的属性占位符非常类似。在这里我们所使用的不是占位符表达式,而是SpEL表达式。在XML配置中,你可以将SpEL表达式传入或的value属性中,或者将其作为p-命名空间或c-命名空间条目的值。

(3)引用bean、属性和方法:SpEL所能做的另外一件基础的事情就是通过ID引用其他的bean。除了引用bean的属性,我们还可以调用bean上的方法。为了避免出现NullPointerException,我们可以使用类型安全的运算符“?.”,这个运算符能够在访问它右边的内容之前,确保它所对应的元素不是null。

(4)在表达式中使用类型:如果要在SpEL中访问类作用域的方法和常量的话,要依赖T()这个关键的运算符。

(5)SpEL运算符:SpEL提供了多个运算符,这些运算符可以用在SpEL表达式的值上。当使用String类型的值时,“+”运算符执行的是连接操作,与在Java中是一样的。SpEL同时还提供了比较运算符,用来在表达式中对值进行对比。比较运算符有两种形式:符号形式和文本形式。在大多数情况下,符号运算符与对应的文本运算符作用是相同的,使用哪一种形式均可以。SpEL还提供了三元运算符(ternary),它与Java中的三元运算符非常类似。

(6)计算正则表达式:SpEL通过matches运算符支持表达式中的模式匹配。matches运算符对String类型的文本(作为左边参数)应用正则表达式(作为右边参数)。matches的运算结果会返回一个Boolean类型的值:如果与正则表达式相匹配,则返回true;否则返回false。

(7)计算集合:“[]”运算符用来从集合或数组中按照索引获取元素,实际上,它还可以从String中获取一个字符。SpEL还提供了查询运算符(.?[]),它会用来对集合进行过滤,得到集合的一个子集。SpEL还提供了另外两个查询运算符:“.”和“.$[]”,它们分别用来在集合中查询第一个匹配项和最后一个匹配项。SpEL还提供了投影运算符(.![]),它会从集合的每个成员中选择特定的属性放到另外一个集合中。


转载地址:https://blog.csdn.net/leif_/article/details/106347102 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:spring实战(3)--面向切面编程
下一篇:spring实战(1)--装配bean

发表评论

最新留言

很好
[***.229.124.182]2024年03月29日 04时16分33秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

domoticz智能家居系统 MQTT 异常以及解决方法 code=14 2019-04-27
智能家居传感器:BME680--树莓派3B+ 搭配BME680的数据读取温湿度和气压。树莓派IIC BME680算法库完整版 2019-04-27
lua语言笔记--注册dll内的函数到全局,lua 全局函数的注册 2019-04-27
工作笔记::c++ 运行命令行脚本 启动lua cmd lua 顺序执行多个文件的方法 c++ 开启一个命令行的方法 lua 启动多个文件 2019-04-27
工作笔记::lua 打印 一个table的方法 2019-04-27
工作笔记::VSCode使用笔记--VSCode 设置自定义快捷键 设置自定义运行脚本 2019-04-27
笔记--记录一次在libmodbus通讯过程socket的connect()遇到的Operation now in progress 的bug 2019-04-27
modbus调试工具开发(1)--windows下编译libmodbus库文件 2019-04-27
工作笔记-- 嵌入式linux设备的端口回收设置 2019-04-27
工作笔记--batch脚本语言的使用随笔--嵌入式linux的一种开发方法的介绍 2019-04-27
工作笔记 -- AltiumDesigner20 设置铺铜改变之后自动重新铺铜方法 2019-04-27
ethcat学习笔记:ethcat 进行FOE升级报错误代码0x8004的原因、分析以及解决方法 2019-04-27
嵌入式linux 学习笔记--如何使用udhcpc获取动态IP 2019-04-27
工作笔记--CMake使用笔记 配合libmodbus 分别编译出x86的服务器版本和arm的嵌入式linux版本 2019-04-27
嵌入式linux学习笔记--2021-01-16-- 字符设备驱动开发笔记 2019-04-27
学习笔记--CPU频率控制软件的使用以及 MobaXterm经常断开的解决方法 2019-04-27
工作笔记--安装twincat之后网卡不能正常使用的解决方法 2019-04-27
嵌入式linux笔记--2021-01-17--基于野火i.mx6ullPRO的 ADC字符设备驱动程序 2019-04-27
嵌入式linux学习笔记-- ubuntu欢迎信息分析 2019-04-27
嵌入式linux学习笔记--IPC(inter-process-commuction,进程间通讯)三种方式之一---- linux下的共享内存的使用方法 2019-04-27