四、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. ...
随机推荐
- saltstack源码-启动1
决定看salt的源码了.干脆就从最基本的看起来,先看它的启动过程开始第一步用/etc/init.d/salt-master start 启动找到那个文件,发现有3种启动方式,suse,debian,c ...
- vs2010统计代码行数
参考:http://www.cnblogs.com/zfanlong1314/archive/2013/03/08/2950100.html 正则表达式:^:b*[^:b#/]+.*$ 文件类型:*. ...
- Luogu P1137 旅行计划 【拓扑排序+Dp】By cellur925
题目传送门 由于满足游览先后顺序从西到东的性质,我们很自然的想到用拓扑排序处理出一个合理的游览顺序. 然鹅,之后呢? 事实上,拓扑排序常与Dp相结合,解决后效性.我们就可以在每次拓扑入队的时候更新答案 ...
- jQuery笔记之animate中的queue
队列 队列的执行顺序 queue() dequeue() 输出对象里面的内容 依次出队 不过这样写太麻烦了,因为每次都要输出,所以我们看下面的方法 运用到队列输出的 <!DOCTYPE html ...
- 前缀+排序 HDOJ 4311 Meeting point-1
题目传送门 题意:给一些坐标轴上的点,选一个点,使得其他点到该点曼哈顿距离和最小 分析:这题有很强的技巧性,直接计算每个点的曼哈顿距离和是不可行的.这里用到了前缀的思想,先对点按照x从左到右排序,p[ ...
- 数学 SCU 4436 Easy Math
题目传送门 /* 数学题:当有一个数开根号后是无理数,则No */ #include <cstdio> #include <algorithm> #include <cs ...
- 数学 Codeforces Round #308 (Div. 2) B. Vanya and Books
题目传送门 /* 水题:求总数字个数,开long long竟然莫名其妙WA了几次,也没改啥又对了:) */ #include <cstdio> #include <iostream& ...
- PWA之serviceWorker应用
1.serviceWorker介绍service worker是一段运行在浏览器后台的JavaScript脚本,在页面中注册并安装成功后,它可以拦截和处理网络请求,实现缓存资源并可在离线时响应用户的请 ...
- java 缓冲流 Buffer
缓冲流 Buffer :设置缓冲区加快执行效率 子类: (一)BufferedInputStream : 缓冲输入字节流 ,目的:提高读取文件的效率 注意: BufferedInputStream ...
- 【intellij idea】汇总
1 右键无法创建,找不到scala class https://blog.csdn.net/u011513853/article/details/52896230 2 缩进 https://jingy ...