??xml version="1.0" encoding="utf-8" standalone="yes"?> Ordering是Guavacd提供的一个犀利强大的比较器工PGuava的Ordering和JDK Comparator相比功能更强。它非常Ҏ(gu)扩展Q可以轻松构造复杂的comparatorQ然后用在容器的比较、排序等操作中?/p> 本质上来_(d)Ordering 实例无非是一个特D的Comparator 实例。Ordering只是需要依赖于一个比较器Q例如,Collections.maxQ的Ҏ(gu)Qƈ使其可作为实例方法。另外,Ordering提供了链式方法调用和加强现有的比较器?/p> 下面我们看看Ordering中的一些具体方法和单的使用实例?/p> 常见的静态方法:(x) natural()Q?/strong>使用Comparablecd的自焉序, 例如Q整C到大,字符串是按字兔R? 单实例:(x) 输出Q?/p> 操作Ҏ(gu)Q?/p> reverse(): q回与当前Ordering相反的排?
]]>
2 <bean name="pathExtensionContentNegotiationStrategy"
3 class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
4 <constructor-arg>
5 <props>
6 <!-- if romePresent -->
7 <prop key="atom">application/atom+xml</prop>
8 <prop key="rss">application/rss+xml</prop>
9 <!-- endif -->
10 <!-- if jackson2Present || jacksonPresent -->
11 <prop key="json">application/json</prop>
12 <!-- endif -->
13 <!-- if jaxb2Present -->
14 <prop key="xml">application/xml</prop>
15 <!-- endif -->
16 </props>
17 </constructor-arg>
18 </bean>
19
20 <!-- 配置映射媒体cd的策?nbsp;-->
21 <bean name="mvcContentNegotiationManager"
22 class="org.springframework.web.accept.ContentNegotiationManager">
23 <constructor-arg>
24 <list>
25 <ref bean="pathExtensionContentNegotiationStrategy" />
26 </list>
27 </constructor-arg>
28 </bean>
29
30 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
31 <property name="order" value="0"/>
32 <property name="removeSemicolonContent" value="false"/>
33 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager"/>
34 </bean>
35
36 <!-- 配置数据转换服务Q默认用格式化数据转换服务Q可以对日期和数字进行格式化 -->
37 <bean name="conversionService"
38 class="org.springframework.format.support.DefaultFormattingConversionService">
39 <constructor-arg index="0">
40 <null/>
41 </constructor-arg>
42 <constructor-arg index="1" value="true"/>
43 </bean>
44
45 <bean name="validator"
46 class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
47
48 <!-- 配置数据l定Q通过转换服务实现l定Q如果包含jsr303实现q将q行校验 -->
49 <bean name="webBindingInitializer"
50 class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
51 <property name="conversionService" ref="conversionService" />
52 <!-- if jsr303Present -->
53 <property name="validator" ref="validator" />
54 <!-- endif -->
55 </bean>
56
57 <bean name="byteArrayHttpMessageConverter"
58 class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
59
60 <bean name="stringHttpMessageConverter"
61 class="org.springframework.http.converter.StringHttpMessageConverter">
62 <property name="writeAcceptCharset" value="false" />
63 </bean>
64
65 <bean name="resourceHttpMessageConverter"
66 class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
67 <bean name="sourceHttpMessageConverter"
68 class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
69 <bean name="allEncompassingFormHttpMessageConverter"
70 class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
71 <bean name="atomFeedHttpMessageConverter"
72 class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
73 <bean name="rssChannelHttpMessageConverter"
74 class="org.springframework.http.converter.feed.RssChannelHttpMessageConverter"/>
75 <bean name="jaxb2RootElementHttpMessageConverter"
76 class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
77 <bean name="mappingJacksonHttpMessageConverter"
78 class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
79
80 <!-- 配置@RequestBodyQ@ResponseBody注解可用的{换器 -->
81 <util:list id="messageConverters"
82 list-class="org.springframework.beans.factory.support.ManagedList">
83 <ref bean="byteArrayHttpMessageConverter" />
84 <ref bean="stringHttpMessageConverter" />
85 <ref bean="resourceHttpMessageConverter" />
86 <ref bean="sourceHttpMessageConverter" />
87 <ref bean="allEncompassingFormHttpMessageConverter" />
88 <!-- if romePresent -->
89 <ref bean="atomFeedHttpMessageConverter" />
90 <ref bean="rssChannelHttpMessageConverter" />
91 <!-- endif -->
92 <!-- if jaxb2Present -->
93 <ref bean="jaxb2RootElementHttpMessageConverter" />
94 <!-- endif -->
95 <!-- if jacksonPresent -->
96 <ref bean="mappingJacksonHttpMessageConverter" />
97 <!-- endif -->
98 </util:list>
99
100 <!-- Q意类型的Controller适配为Handler -->
101 <bean name="requestMappingHandlerAdapter"
102 class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
103 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager" />
104 <property name="webBindingInitializer" ref="webBindingInitializer" />
105 <property name="messageConverters" ref="messageConverters" />
106 </bean>
107
108 <!-- q个拦截器暴露{换器服务让spring:bind和spring:eval标签可用 -->
109 <bean name="csInterceptor"
110 class="org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor">
111 <constructor-arg index="0" ref="conversionService"/>
112 </bean>
113
114 <!-- 现在所有拦截器都必设定响应的路径映射 -->
115 <bean name="mappedCsInterceptor"
116 class="org.springframework.web.servlet.handler.MappedInterceptor">
117 <constructor-arg index="0">
118 <null/>
119 </constructor-arg>
120 <constructor-arg index="1" ref="csInterceptor"/>
121 </bean>
122
123 <!-- 使用@ExceptionHandler注解的方法来处理ExceptionQ优先?Q最高) -->
124 <bean name="exceptionHandlerExceptionResolver"
125 class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
126 <property name="contentNegotiationManager" ref="mvcContentNegotiationManager" />
127 <property name="messageConverters" ref="messageConverters" />
128 <property name="order" value="0" />
129 </bean>
130
131 <!-- 如果抛出的Exceptioncd有@ResponseStatus注解Q响应返回该注解的Http状态码Q优先? -->
132 <bean name="responseStatusExceptionResolver"
133 class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver">
134 <property name="order" value="1" />
135 </bean>
136
137 <!-- SpringMvc内部异常处理 -->
138 <bean name="defaultExceptionResolver"
139 class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver">
140 <property name="order" value="2" />
141 </bean>
142
]]>
6.对servlet的每个请求都在一个单独的U程中运行,M特定servletc都只有一个实例?br />
]]>
usingToString() Q?/strong>使用toString()q回的字W串按字兔R序进行排序;
arbitrary() Q?/strong>q回一个所有对象的L序Q?即compare(a, b) == 0 是 a == b (identity equality)?本n的排序是没有M含义Q?但是在VM的生命周期是一个常量?/p>import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class OrderingTest {
@Test
public void testStaticOrdering(){
List<String> list = Lists.newArrayList();
list.add("peida");
list.add("jerry");
list.add("harry");
list.add("eva");
list.add("jhon");
list.add("neron");
System.out.println("list:"+ list);
Ordering<String> naturalOrdering = Ordering.natural();
Ordering<Object> usingToStringOrdering = Ordering.usingToString();
Ordering<Object> arbitraryOrdering = Ordering.arbitrary();
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
System.out.println("usingToStringOrdering:"+ usingToStringOrdering.sortedCopy(list));
System.out.println("arbitraryOrdering:"+ arbitraryOrdering.sortedCopy(list));
}
}list:[peida, jerry, harry, eva, jhon, neron]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
usingToStringOrdering:[eva, harry, jerry, jhon, neron, peida]
arbitraryOrdering:[neron, harry, eva, jerry, peida, jhon]
nullsFirst(): q回一个将null攑֜non-null元素之前的OrderingQ其他的和原始的Ordering一P
nullsLast()Q返回一个将null攑֜non-null元素之后的OrderingQ其他的和原始的Ordering一P
compound(Comparator)Q返回一个用Comparator的OrderingQComparator作ؓ(f)W二排序元素Q例如对bug列表q行排序Q先Ҏ(gu)bug的别,再根据优先q行排序Q?br style="margin: 0px; padding: 0px;" /> lexicographical()Q返回一个按照字典元素P代的OrderingQ?br style="margin: 0px; padding: 0px;" /> onResultOf(Function)Q将function应用在各个元素上之后, 在用原始orderingq行排序Q?br style="margin: 0px; padding: 0px;" /> greatestOf(Iterable iterable, int k)Q返回指定的Wk个可q代的最大的元素Q按照这个从最大到最的序。是不稳定的?br style="margin: 0px; padding: 0px;" /> leastOf(Iterable<E> iterable,int k)Q返回指定的Wk个可q代的最的元素Q按照这个从最到最大的序。是不稳定的?br style="margin: 0px; padding: 0px;" /> isOrdered(Iterable)Q是否有序,Iterable不能于2个元素?br style="margin: 0px; padding: 0px;" /> isStrictlyOrdered(Iterable)Q是否严格有序。请注意QIterable不能于两个元素?br style="margin: 0px; padding: 0px;" /> sortedCopy(Iterable)Q返回指定的元素作ؓ(f)一个列表的排序副本?/p>package com.peidasoft.guava.base;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class OrderingTest {
@Test
public void testOrdering(){
List<String> list = Lists.newArrayList();
list.add("peida");
list.add("jerry");
list.add("harry");
list.add("eva");
list.add("jhon");
list.add("neron");
System.out.println("list:"+ list);
Ordering<String> naturalOrdering = Ordering.natural();
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
List<Integer> listReduce= Lists.newArrayList();
for(int i=9;i>0;i--){
listReduce.add(i);
}
List<Integer> listtest= Lists.newArrayList();
listtest.add(1);
listtest.add(1);
listtest.add(1);
listtest.add(2);
Ordering<Integer> naturalIntReduceOrdering = Ordering.natural();
System.out.println("listtest:"+ listtest);
System.out.println(naturalIntReduceOrdering.isOrdered(listtest));
System.out.println(naturalIntReduceOrdering.isStrictlyOrdered(listtest));
System.out.println("naturalIntReduceOrdering:"+ naturalIntReduceOrdering.sortedCopy(listReduce));
System.out.println("listReduce:"+ listReduce);
System.out.println(naturalIntReduceOrdering.isOrdered(naturalIntReduceOrdering.sortedCopy(listReduce)));
System.out.println(naturalIntReduceOrdering.isStrictlyOrdered(naturalIntReduceOrdering.sortedCopy(listReduce)));
Ordering<String> natural = Ordering.natural();
List<String> abc = ImmutableList.of("a", "b", "c");
System.out.println(natural.isOrdered(abc));
System.out.println(natural.isStrictlyOrdered(abc));
System.out.println("isOrdered reverse :"+ natural.reverse().isOrdered(abc));
List<String> cba = ImmutableList.of("c", "b", "a");
System.out.println(natural.isOrdered(cba));
System.out.println(natural.isStrictlyOrdered(cba));
System.out.println(cba = natural.sortedCopy(cba));
System.out.println("max:"+natural.max(cba));
System.out.println("min:"+natural.min(cba));
System.out.println("leastOf:"+natural.leastOf(cba, 2));
System.out.println("naturalOrdering:"+ naturalOrdering.sortedCopy(list));
System.out.println("leastOf list:"+naturalOrdering.leastOf(list, 3));
System.out.println("greatestOf:"+naturalOrdering.greatestOf(list, 3));
System.out.println("reverse list :"+ naturalOrdering.reverse().sortedCopy(list));
System.out.println("isOrdered list :"+ naturalOrdering.isOrdered(list));
System.out.println("isOrdered list :"+ naturalOrdering.reverse().isOrdered(list));
list.add(null);
System.out.println(" add null list:"+list);
System.out.println("nullsFirst list :"+ naturalOrdering.nullsFirst().sortedCopy(list));
System.out.println("nullsLast list :"+ naturalOrdering.nullsLast().sortedCopy(list));
}
}
//============输出==============
list:[peida, jerry, harry, eva, jhon, neron]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
listtest:[1, 1, 1, 2]
true
false
naturalIntReduceOrdering:[1, 2, 3, 4, 5, 6, 7, 8, 9]
listReduce:[9, 8, 7, 6, 5, 4, 3, 2, 1]
true
true
true
true
isOrdered reverse :false
false
false
[a, b, c]
max:c
min:a
leastOf:[a, b]
naturalOrdering:[eva, harry, jerry, jhon, neron, peida]
leastOf list:[eva, harry, jerry]
greatestOf:[peida, neron, jhon]
reverse list :[peida, neron, jhon, jerry, harry, eva]
isOrdered list :false
isOrdered list :false
add null list:[peida, jerry, harry, eva, jhon, neron, null]
nullsFirst list :[null, eva, harry, jerry, jhon, neron, peida]
nullsLast list :[eva, harry, jerry, jhon, neron, peida, null]
]]>
]]>
数据库事务的隔离U别?个,׃到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable Q这四个U别可以逐个解决脏读 、不可重复读 、?nbsp;q几c问题?/span>
√: 可能出现 ×: 不会(x)出现
脏读 | 不可重复?/span> | q读 | |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
注意Q我们讨论隔ȝ别的场景Q主要是在多个事务ƈ?nbsp;的情况下Q因此,接下来的讲解都围l事务ƈ发?/span>
公司发工资了Q领导把5000元打到singo的̎号上Q但是该事务q未提交Q而singo正好L看̎P发现工资已经到̎Q是5000元整Q非帔R 兴。可是不q的是,领导发现发给singo的工资金额不对,?000元,于是q速回滚了事务Q修攚w额后Q将事务提交Q最后singo实际的工资只?2000元,singoI欢喜一场?/span>
出现上述情况Q即我们所说的脏读 Q两个ƈ发的事务Q?#8220;事务AQ领导给singo发工?#8221;?#8220;事务BQsingo查询工资账户”Q事务Bd了事务A未提交的数据?/span>
当隔ȝ别设|ؓ(f)Read uncommitted Ӟ可能出现脏读,如何避免脏读Q请看下一个隔ȝ别?/span>
singo拿着工资卡去消费Q系l读取到卡里实?000元,而此时她的老婆也正好在|上转̎Q把singo工资卡的2000元{到另一账户Qƈ?singo之前提交了事务,当singo扣款Ӟpȝ查到singo的工资卡已经没有钱,扣款p|Qsingo十分U闷Q明明卡里有钱,??.....
出现上述情况Q即我们所说的不可重复?nbsp;Q两个ƈ发的事务Q?#8220;事务AQsingo消费”?#8220;事务BQsingo的老婆|上转̎”Q事务A事先d了数据,事务B紧接了更C数据Qƈ提交了事务,而事务A再次d该数据时Q数据已l发生了改变?/span>
当隔ȝ别设|ؓ(f)Read committed Ӟ避免了脏读,但是可能?x)造成不可重复诅R?/span>
大多数数据库的默认别就是Read committedQ比如Sql Server , Oracle。如何解决不可重复读q一问题Q请看下一个隔ȝ别?/span>
当隔ȝ别设|ؓ(f)Repeatable read Ӟ可以避免不可重复诅R当singo拿着工资卡去消费Ӟ一旦系l开始读取工资卡信息Q即事务开始)Qsingo的老婆׃可能对该记录q行修改Q也是singo的老婆不能在此时{账?/span>
虽然Repeatable read避免了不可重复读Q但q有可能出现q读 ?/span>
singo的老婆工作在银行部门,Ҏ(gu)帔R过银行内部pȝ查看singo的信用卡消费记录。有一天,Ҏ(gu)在查询到singo当月信用卡的L贚w?Qselect sum(amount) from transaction where month = 本月Qؓ(f)80元,而singo此时正好在外面胡吃v塞后在收银台买单Q消?000元,x增了一?000元的消费记录Qinsert transaction ... Q,q提交了事务Q随后singo的老婆singo当月信用卡消费的明细打印到A4U怸Q却发现消费总额?080元,singo的老婆很诧异,以ؓ(f)?Cq觉Qdq样产生了?/span>
注:(x)Mysql的默认隔ȝ别就是Repeatable read?/span>
Serializable 是最高的事务隔离U别Q同时代价也p最高,性能很低Q一般很用,在该U别下,事务序执行Q不仅可以避免脏诅R不可重复读Q还避免了像读?/span>
Google是一个非怼U的公司。他们做Z很多令hU赞的东?#8212;既是公司外部Qh们可以看到的东西Q也是公司内部。有一些在公司内部q不属于保密的事情,在外部ƈ没有l予_q泛的讨论。这是我今天要说的?/p>
让Google的程序如此优U的一个最重要的事情看h是非常的单:(x)代码审查。ƈ不是只有Google做这个事?#8212;代码审查已经被广泛的认可ZU非常好的做法,很多人都在这样做。但我还没有看到W二家这样大的公司能把这U事情运用的如此普遍。在GoogleQ?strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; background: transparent;">没有E序QQ何品、Q何项目的E序代码Q可以在没有l过有效的代码审查前提交C码库里的?/p>
所有h都要l过代码审查。ƈ且很正规的:(x)q种事情应该成ؓ(f)M重要的Y件开发工作中一个基本制度。ƈ不单指品程?#8212;—所有东ѝ它不需要很多的工作Q但它的效果是巨大的?/p>
从代码审查里能得C么?
很显Ӟ(x)在代码提交前Q用W二眼睛检查一遍,防止bug混入。这是对其最常见的理解,是对代码审查的好处的最q泛的认识。但是,依我的经验来看,q反倒是?strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; background: transparent;">最不重?/strong>的一炏Vh们确实在代码审查中找Cbug。可是,q些在代码审查中能发现的l大部分bugQ很昄Q都是微不道的bugQ程序的作者花几分钟的旉p发现它们。真正需要花旉d现的bug不是在代码审查里能找到的?/p>
代码审查的最大的功用是纯C会(x)性的。如果你在编E,而且知道会(x)有同事检查你的代码,你编E态度完全不一样了。你写出的代码将更加整洁Q有更好的注释,更好的程序结?#8212;—因ؓ(f)?strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; background: transparent;">知道Q那个你很在意的人将?x)查看你的程序。没有代码审查,你知道h们最l还是会(x)看你的程序。但q种事情不是立即发生的事Q它不会(x)l你带来同等的紧q感Q它不会(x)l你相同的个判的那种感受?/p>
q有一个非帔R要的好处。代码审查能传播知识。在很多的开发团队里Q经常每一个h负责一个核心模块,每个人都只关注他自己的那个模块。除非是同事的模块媄响了自己的程序,他们从不怺交流。这U情늚后果是,每个模块只有一个h熟?zhn)里面的代码。如果这个h休假?#8212;—但愿不是——辞职了,其他人则束手无策。通过代码审查Q至会(x)有两个h熟?zhn)q些E序——作者,以及(qing)审查者。审查者ƈ不能像程序的作者一样对E序十分了解——但他?x)熟?zhn)程序的设计和架构,q是极其重要的?/p>
当然Q没有什么事情能单的做下来的。依我的l验Q在你能正确的进行代码审查前Q你需要花旉ȝ学习(fn)。我发现Z在代码审查时l常?x)犯一些错误,D不少ȝ——其在一些缺乏经验的审查者中l常的出玎ͼ他们l了Z一个很遭的代码审查的体验,成ؓ(f)了h们接受代码审查制度的一个障?/p>
最重要的一个原则:(x)代码审查用意是在代码提交前找到其中的问题——你要发现是它?strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; background: transparent;">正确。在代码审查中最常犯的错?#8212;—几乎每个新手都会(x)犯的错误——是,审查者根据自q~程?fn)惯来评判别人的代码?/p>
对于一个问题,通常我们能找出十几种Ҏ(gu)去解冟뀂对于一U解x案,我们能有百万U编码方案来实现它。作Z个审查者,你的d不是来确保被审查的代码都采用的是你的~码风格——因ؓ(f)它不可能跟你写的一栗作ZD代码的审查者的d是确保由作者自己写出的代码是正的。一旦这个原则被打破Q你最l将?x)倍感折磨Q深受挫?#8212;—q可不是我们惌的结果?/p>
问题在于Q这U错误是如此的普遍而易犯。如果你是个E序员,当你遇到一个问题,你能惛_一U解x?#8212;—你就把你惛_的方案作为标准答案。但事情不是q样?#8212;—作ؓ(f)一个好的审查者,你需要明白这个道理?/p>
代码审查的第二个易犯的毛病是Qh们觉得有压力Q感觉非要说点什么才好。你知道作者用了大量的旉和精力来实现q些E序——不该说点什么吗Q?/p>
不,你不需要?/p>
只说一?#8220;哇,不错呀”QQ何时候都不会(x)不合适。如果你L力图扑և一点什么东西来批评Q你q样做的l果只会(x)损害自己的威望。当你不厌其烦的扑և一些东西来Q只是ؓ(f)了说些什么,被审查h׃(x)知道Q你说这些话只是Z填补寂静。你的评论将不再被h重视?/p>
W三是速度。你不能匆匆忙忙的进行一ơ代码审?#8212;—但你也要能迅速的完成。你的同伴在{你。如果你和你的同事ƈ不想花太多时间进行代码复查,你们很快的完成,那被审查者会(x)觉得很沮丧,q种代码审查带来的只有失望的感觉。就好象是打搅了大家Q大家放下手头的工作来q行审查。事情不该是q样。你q不需要推掉手头上的Q何事情来做代码审查。但如果中途耽误了几个小Ӟ你中间还要休息一?x),喝杯Ӟ冲个澡,或谈会(x)儿闲话。当你回到审查现场,你可以l下去,把事情做完。如果你真是q样Q我x有h愿意在那q等着你?/p>