四、spring中高级装配(2)
这个是接着上一篇写的,这章内容较多,分开来记录一下。。。
三、处理自动装配的歧义性
自动装配让spring完全负责bean引用注入到构造参数和属性中,不过,仅有一个bean匹配所需的结果时,自动装配才是有效的。如果不仅有一个bean能够匹配的话,这种歧义性会阻碍spring自动装配属性、构造参数或方法参数。虽然这种歧义性十分罕见,但是我看了spring解决方法后,感觉spring提供的是一种这类问题的解决办法,显然在这里主要学习的是这种解决此类问题的思想。
//这里是提供了这种特殊情况的demo,有一个方法,需要自动装配Dessert接口
@Autowired
public void setDessert(Dessert dessert){
this.dessert = dessert;
} //但是这个Dessert接口却有三个实现类,这就有点尴尬了,spring自动装配的时候到底要装配哪个实现类呢..... spring会报NoUniqueBeanDefinitionException错误的 @Component
public class Cake implements Dessert{......} @Component
public class Cookies implements Dessert{......} @Component
public class IceCream implements Dessert{......} //使用@Primary 注解标注首选bean
@Primary
@Component
public class IceCream implements Dessert{......} <bean id="iceCream" class="com.desserteater.IceCream" primary="true" /> //但是两个同时加上@Primary注解呢!!!spring中会有@Qualifier注解
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert){
this.dessert = dessert;
} //但是这种方式使用的是bean ID,限制符与要注入的bean是紧耦合的,对类名称的改动都会导致限定符失效,但是spring中允许为bean设置自己的限定符
@Component
@Qualifier("cold")
public class IceCream implements Dessert{......} @Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert){
this.dessert = dessert;
} //但是如果是两个实现类具有相同特点的限制符呢!!!这个考虑的也太全面了吧,程序员就是要有这种精神的,哈哈哈,就是下面这种情况呢..... @Component
@Qualifier("cold")
@Qualifier("creamy")
public class IceCream implements Dessert{......} @Component
@Qualifier("cold")
@Qualifier("fruity")
public class Popsicle implements Dessert{......} //Java 中不允许出现在同一个条目上出现相同类型的多个注解的,唉,终极办法:自定义限制符注解,这个好牛叉牛叉...
//这个对应着就是@Qualifier("cold")
@Target({ElementType.CONSTRUCAOR, ElementType.FILELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
Public @interface Cold{} //这个对应着就是@Qualifier("creamy")
@Target({ElementType.CONSTRUCAOR, ElementType.FILELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
Public @interface Creamy{} //这个对应着就是@Qualifier("fruity")
@Target({ElementType.CONSTRUCAOR, ElementType.FILELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
Public @interface Fruity{} //大功告成,这就彻底解决那个问题了,你在有多少的我也不怕了,嘿嘿嘿,完美的解决这个问题了,spring中太美妙了,这种思想真的让人受益匪浅
@Component
@Cold
@Creamy
public class IceCream implements Dessert{......} @Component
@Cold
@Fruity
public class Popsicle implements Dessert{......} @Autowired
@Cold
@Creamy
public void setDessert(Dessert dessert){
this.dessert = dessert;
}
四、bean的作用域
在默认情况下,spring应用上下文中所有的bean都是以单例的形式创建的,也就是说,不管给定的一个bean被注入到其他bean多少次,每次所注入的都是同一个实例。大多数情况下,单例bean是很理想的方案。初始化和垃圾回收对线实例所带来的成本只留给一些小规模的任务,在这些任务中,让对象保持无状态并且在应用中反复用这些对象可能并不合理。
spring中为解决这个问题,定义了多种作用域,可以基于这些作用域创建bean:
1)单例(Singleton):在整个应用中,只创建bean的一个实例
2)原型(Prototype):每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean的实例
3)会话(Session):在web应用中,为每个会话创建一个bean实例
4)请求(Request):在web应用中,为每个请求创建一个bean实例
//Prototype 原型作用域的配置方式
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad{......} <bean id="notepad" class="com.myapp.Notepad" scope="prototype" /> //Session 会话和 Request 请求作用域
//在电商领域的 处理购物车bean 会话作用域是最合适的
@Component
@Scope(
value=WebApplicationContext.Scope.SESSION,
ProxyMode=ScopedProxyMode.INTERFACES)
Public ShoppingCart cart(){......} @Component
Public class StoreService(){ //StoreService是一个单例bean,会在spring应用上下文加载的时候创建,当它创建的时候,会试图将ShoppingCart bean注入到set方法中,但是ShoppingCart bean是会话作用域,此时并不存在,直到某个用户进入系统,创建会话之后才会出现ShoppingCart 的实例
@Autowired
public void setShoppingCart(ShoppingCart shoppingCart){
this.shoppingCart = shoppingCart;
}
} /*
这里需要详细讲解一下ProxyMode
系统中,会有多个ShoppingCart 的实例,每个用户一个,我们希望当StoreService处理购物车的时候,它所使用的ShoppingCart 实例恰好是当前会话所对应的那一个 spring并不会将实际的ShoppingCart bean注入到StoreService中,spring会注入一个到ShoppingCart bean的代理,这个代理会暴露于ShoppingCart 相同的方法,StoreService会认为它就是一个购物车 当StoreService 调用 ShoppingCart 的方法时,代理会对其进行懒解析并调用委托给会话作用域内真正的ShoppingCart bean 这个东西好牛气的样子,这里涉及到了代理模式
*/ //注意:ScopedProxyMode.INTERFACES 表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean
//注意:ScopedProxyMode.TARGET_CLASS 实现的是一个具体的类的话,spring必须使用CGLib 来生成基于类的代理 //XML中实现作用域的配置 这里用到了AOP Spring中面向切面
<bean id="cart" class="com.myapp.ShoppingCart">
<aop:scoped=proxy /> //spring会默认CGLib创建目标类的代理
</bean> //这种 proxy-target-class="false" spring会创建基于接口的代理
<bean id="cart" class="com.myapp.ShoppingCart">
<aop:scoped=proxy proxy-target-class="false" />
</bean>
五、运行时值注入
这节主要讲的就是spring中的表达式语言SpEL,其他的基本上没有特别重要的,值得思考的知识点。
spring提供了两种在运行时求值的方式:
(1)属性占位符(Property placeholder)
(2)Spring 表达式语言(SpEL)
属性占位符的语法是:${.....}
主要来说一下Spring 表达式语言(SpEL)
1、SpEL拥有很多特性,主要包括:
1)使用bean的ID来应用bean
2)调用方法和访问对象的属性
3)对值进行算术、关系和逻辑运算
4)正则表达式匹配
5)集合操作
2、SpEL样例
1)表示String值、浮点数、Boolean值
#{3.14159}
#{9.87E4} 对应着 98700
#{“hello”}
#{true}
2)引用bean、属性和方法
#{sgtPeppers}
#{sgtPeppers.artist}
#{sgtPeppers.selectArtist()}
#{sgtPeppers.selectArtist().toUpperCase()}
#{sgtPeppers.selectArtist()?.toUpperCase()} 避免出现空值,出现?避免出现空值
3)在表达式中使用类型
T{java.lang.Math}
T{java.lang.Math}.PI
T{java.lang.Math}.random()
4)SpEL运算符
#{2*T{java.lang.Math}.PI*circle.radius}
#{T(java.lang.Math).PI*circle.radius^2}
#{disc.title + 'by' + disc.artist}
#{counter.total == 100}
#{counter.total eq 100}
#{score > 100 ? "winner" : "loser"}
5)计算正则表达式
#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9._]+\\.com'}
6)计算集合
#{jukebox.songs[4].title}
#{jukebox.songs[T(java.lang.Math).random * jukebox.songs.size()].title}
#{jukebox.songs.?[artist eq 'Aerosmith']} 过滤歌曲,得到所有属性为Aerosmith的歌曲的小的集合
#{jukebox.songs.^[artist eq 'Aerosmith']} 查询集合中第一个属性为Aerosmith的歌曲
#{jukebox.songs.![title]} 投影运算符,将集合中的特定的属性放到一个新集合中去
#{jukebox.songs.?[artist eq 'Aerosmith']}.![title] 混合使用,把作者是Aerosmith的title属性放到一个集合中去
四、spring中高级装配(2)的更多相关文章
- 三、spring中高级装配(1)
大概看了一下第三章的内容,我从项目中仔细寻找,始终没有发现哪里有这种配置,但是看完觉得spring还有这么牛B的功能啊,spring的厉害之处,这种设计程序的思想,很让我感慨... 一.环境与prof ...
- Spring高级装配
Spring高级装配 目录 一.Profile(根据开发环境创建对应的bean) 二.条件化的创建bean(根据条件创建bean) 三.处理自动装配歧义性(指定首选bean.限定符限制bean) 四. ...
- Spring(3)——装配 Spring Bean 详解
装配 Bean 的概述 前面已经介绍了 Spring IoC 的理念和设计,这一篇文章将介绍的是如何将自己开发的 Bean 装配到 Spring IoC 容器中. 大部分场景下,我们都会使用 Appl ...
- J2EE进阶(四)Spring配置文件详解
J2EE进阶(四)Spring配置文件详解 前言 Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸".Java EE程 ...
- Spring系列七:Spring 自动装配
相思相见知何日?此时此夜难为情. 概述 在Spring框架中,在配置文件中声明bean的依赖关系是一个很好的做法,因为Spring容器能够自动装配协作bean之间的关系.这称为spring自动装配. ...
- Spring自动装配(二)
为什么Spring要支持Autowire(自动装配) 先写几个类,首先定义一个Animal接口表示动物: 1 public interface Animal { 2 3 public void eat ...
- Spring 自动装配 Bean
Spring3系列8- Spring 自动装配 Bean 1. Auto-Wiring ‘no’ 2. Auto-Wiring ‘byName’ 3. Auto-Wiri ...
- Axis2(7):将Spring的装配JavaBean发布成WebService
在现今的Web应用中经常使用Spring框架来装载JavaBean.如果要想将某些在Spring中装配的JavaBean发布成WebService,使用Axis2的Spring感知功能是非常容易做到的 ...
- Spring注解装配
Spring 自动装配的主机有 @Autowired.@Intect.@Resource @Autowired是byType的, @Resource是byName的.我们一般用@Atutowired. ...
随机推荐
- STM32F4 DMA2D_R2M
图像处理的专门DMA 看一段示例代码 /** * @brief Displays a line. * @param Xpos: specifies the X position. * @param Y ...
- OC:基础总结
OC面向对象的编程语言思想 类与对象.继承与实例化.属性点语法.内存管理.字符串.可见度. 类是一组具有相同特征和行为的事物的抽象 OC的与C相比所具有的新的特点: 定义新的类.类的实例和方法.方法的 ...
- 从事UNIX/LInux服务器编程最方便的代码编译工具------(eclipse for c/c++)、(FileZilla)、(Secure CRT) 这三种一定要一起使用 之1
今天主要是将前几天搞的Linux学习的心得写出来,希望帮助更多的人进行,方便从事Unix和Linux编程的同行和刚入门者.主要介绍三种工具并给出安装过程,请大家不必怀疑这个博文,此博文是我自己原创.请 ...
- 阿里DNS 223.5.5.5 223.6.6.6 (转载)
转自:http://it.oyksoft.com/post/6780/ 阿里DNS: 223.5.5.5 223.6.6.6 为何用它? 一.选择阿里DNS让你购物更爽,如果是淘宝狂人 ...
- eclipse集成lombok注解不起作用
安装步骤: 步骤一:lombok的下载地址为:https://projectlombok.org/download,jar包很小.这里也把依赖写出来: <dependency> <g ...
- 洛谷 P4552 [Poetize6] IncDec Sequence【差分+脑洞】
一看区间操作,很容易想到差分 所以就是先差分,然后为了保证最小步数,把政府差分抵消,也就相当于原数组区间加减 第二问,因为差分数组抵消之后不为0就需要使用n+1的虚拟位置,而这个的值其实没有,所以我们 ...
- 洛谷 P2754 星际转移问题【最大流】
判无解的方法非常粗暴:快T了还是没有合法方案,就是无解. 然后枚举答案,对于每一天都建一套太空站,s连地球,t连月球,上一天的太空站连向这一天的太空站,流量均为inf.然后对于每个飞船,上一天的停靠站 ...
- Kerberos原理和基础小结
此篇文章仅做Kerberos的基本原理和基本使用做说明,本人对Kerberos了解有限,也是通过大量英文文档中翻译过来, 加上自己对Kerberos的理解所写,本人英文太菜,看文档看的头昏眼花若有写的 ...
- 构造 HDOJ 5400 Arithmetic Sequence
题目传送门 题意:问有多少个区间,其中存在j使得ai + d1 == ai+1(i<j) && ai + d2 == ai+1 (i>j) 构造:用c1[i], c2[i] ...
- 题解报告:poj 2185 Milking Grid(二维kmp)
Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that ...