Spring 2.x在配置文件的簡化的方面做了很多工作,原來1.x中比較麻煩的配置都已經擁有了比較完美的解決方案。最近剛看完《精通Spring 2.x --企業應用開發精解》的書,結合自己的經驗整理一下簡化配置的內容。
一、關于集合的配置
1.List
>1.x版本的
- <bean id="parentBoss" abstract="true"class="com.baobaotao.attr.Boss"> <--父<bean>
- <property name="favorites">
- <set>
- <value>看報</value>
- <value>賽車</value>
- <value>高爾夫</value>
- </set>
- </property>
- </bean>
<bean id="parentBoss" abstract="true"class="com.baobaotao.attr.Boss"> <--父<bean>
<property name="favorites">
<set>
<value>看報</value>
<value>賽車</value>
<value>高爾夫</value>
</set>
</property>
</bean>
>2.x版本的
- <util:list id="favoriteList1" list-class="java.util.LinkedList">
- <value>看報</value>
- <value>賽車</value>
- <value>高爾夫</value>
- </util:list>
<util:list id="favoriteList1" list-class="java.util.LinkedList">
<value>看報</value>
<value>賽車</value>
<value>高爾夫</value>
</util:list>
2.Set
> 1.x
- <bean id="boss1" class="com.baobaotao.attr.Boss">
- <property name="favorites">
- <set>
- <value>看報</value>
- <value>賽車</value>
- <value>高爾夫</value>
- </set>
- </property>
- </bean>
<bean id="boss1" class="com.baobaotao.attr.Boss">
<property name="favorites">
<set>
<value>看報</value>
<value>賽車</value>
<value>高爾夫</value>
</set>
</property>
</bean>
> 2.x
-
- <util:set id="favoriteSet1">
- <value>看報</value>
- <value>賽車</value>
- <value>高爾夫</value>
- </util:set>
<util:set id="favoriteSet1">
<value>看報</value>
<value>賽車</value>
<value>高爾夫</value>
</util:set>
3.Map
> 1.x
- <bean id="boss1" class="com.baobaotao.attr.Boss">
- <property name="jobs">
- <map>
- <!--Map第一個元素-->
- <entry>
- <key><value>AM</value></key>
- <value>會見客戶</value>
- </entry>
- <!--Map第二個元素-->
- <entry>
- <key><value>PM</value></key>
- <value>公司內部會議</value>
- </entry>
- </map>
- </property>
- </bean>
<bean id="boss1" class="com.baobaotao.attr.Boss">
<property name="jobs">
<map>
<!--Map第一個元素-->
<entry>
<key><value>AM</value></key>
<value>會見客戶</value>
</entry>
<!--Map第二個元素-->
<entry>
<key><value>PM</value></key>
<value>公司內部會議</value>
</entry>
</map>
</property>
</bean>
> 2.x
- <util:map id="emails1">
- <entry key="AM" value="會見客戶" />
- <entry key="PM" value="公司內部會議" />
- </util:map>
<util:map id="emails1">
<entry key="AM" value="會見客戶" />
<entry key="PM" value="公司內部會議" />
</util:map>
4. Properties
> 1.x
- <bean id="boss1" class="com.baobaotao.attr.Boss">
- <property name="mails">
- <props>
- <prop key="jobMail">john-office@baobaotao.com</prop>
- <prop key="lifeMail">john-life@baobaotao.com</prop>
- </props>
- </property>
- </bean>
<bean id="boss1" class="com.baobaotao.attr.Boss">
<property name="mails">
<props>
<prop key="jobMail">john-office@baobaotao.com</prop>
<prop key="lifeMail">john-life@baobaotao.com</prop>
</props>
</property>
</bean>
> 2.x
- <util:properties id="emailProps1" location="classpath:com/baobaotao/fb/mails.properties"/>
<util:properties id="emailProps1" location="classpath:com/baobaotao/fb/mails.properties"/>
可以在一個屬性文件中直接配置屬性,這比較符合一般的項目習慣。
二、 關于事務配置
1.1.x
- <bean id="bbtForum"
- class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
- <property name="transactionManager" ref="txManager" />
- <property name="target" ref="bbtForumTarget"/>
- <property name="transactionAttributes">
- <props>
- <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="*">PROPAGATION_REQUIRED</prop>
- </props>
- </property>
- </bean>
<bean id="bbtForum"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager" />
<property name="target" ref="bbtForumTarget"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
2.2.x
有兩種新方法
a)使用@Transactional注解
在需要的服務類或服務方法處直接打上@Transactional注解,然后在Spring配置文件中啟用注解事務驅動就可以了:
- @Transactional
- public class BbtForumImpl implements BbtForum {
- @Transactional(readOnly=true)
- public Forum getForum(int forumId) {
- return forumDao.getForum(forumId);
- }
- 。。。。
- }
@Transactional
public class BbtForumImpl implements BbtForum {
@Transactional(readOnly=true)
public Forum getForum(int forumId) {
return forumDao.getForum(forumId);
}
。。。。
}
在Spring配置文件中相應添加上:
- <bean id="txManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
- <tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
這樣就OK了,簡單吧:)
b)使用aop/tx
如果你的Service服務類都很規范,我覺得使用aop/tx更方面,因為不用到處打注解,在一處集中配置就OK了,可謂運籌帷幄之中,決勝于千里之外:)
- <aop:config>
- t;aop:pointcut id="serviceMethod"
- expression="execution(* com.baobaotao.service.*Forum.*(..))" />
- t;aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
- </aop:config>
- <tx:advice id="txAdvice" transaction-manager="txManager">
- <tx:attributes>
- <tx:method name="get*" read-only="false"/>
- <tx:method name="add*" rollback-for="Exception" />
- <tx:method name="update*"/>
- </tx:attributes>
- lt;/tx:advice>
<aop:config>
<aop:pointcut id="serviceMethod"
expression="execution(* com.baobaotao.service.*Forum.*(..))" />
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="false"/>
<tx:method name="add*" rollback-for="Exception" />
<tx:method name="update*"/>
</tx:attributes>
</tx:advice>
三、關于AOP配置
原來1.x的AOP太麻煩了,提都不想提,直接說一下2.x的AOP。
Spring 2.x使用@AspectJ來描述切面,由于@AspectJ的語法描述能力超強,因此在Spring 2.x中使用AOP真的非常方便。
在使用@AspectJ之前,首先你得保證你所使用的JDK的版本是5.0及以上版本,否則無法使用注解技術。
Spring在處理@Aspect注解表達式時,需要使用位于spring/lib/asm下asm關聯類庫,將該類庫的三個類包加入到類路徑中:asm-2.2.2.jar、asm-commons-2.2.2.jar和asm-util-2.2.2.jar。我們在第一章中了解了asm類庫的用途,它是輕量級的字節碼處理框架,因為Java的反射機制無法獲取入參名,Spring就利用asm處理@AspectJ中所描述的方法入參名。
此外,Spring采用AspectJ提供的@AspectJ注解類庫及相應的解析類庫,它位于spring/lib/aspectj目錄下,將目錄下的aspectjrt.jar和aspectjweaver.jar類包加入類路徑中。
在做好上節中所提到的前置工作后,我們就可以開始編寫一個基于@AspectJ的切面了,首先來看一個簡單的例子,以便對@AspectJ有一個切身的認識。
@AspectJ采用不同的方式對AOP進行描述, 我們使用NaiveWaiter的例子來說明,這是一個希望引入切面的目標類:
- package com.baobaotao;
- public class NaiveWaiter implements Waiter {
- public void greetTo(String clientName) {
- System.out.println("NaiveWaiter:greet to "+clientName+"...");
- }
- public void serveTo(String clientName){
- System.out.println("NaiveWaiter:serving "+clientName+"...");
- }
- }
package com.baobaotao;
public class NaiveWaiter implements Waiter {
public void greetTo(String clientName) {
System.out.println("NaiveWaiter:greet to "+clientName+"...");
}
public void serveTo(String clientName){
System.out.println("NaiveWaiter:serving "+clientName+"...");
}
}
下面使用@AspectJ來定義一下切面:
- package com.baobaotao.aspectj.aspectj;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
-
- @Aspect
- public class PreGreetingAspect{
- @Before("execution(* greetTo(..))")
- public void beforeGreeting(){
- System.out.println("How are you");
- }
- }
package com.baobaotao.aspectj.aspectj;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//通過該注解將PreGreetingAspect標識為一個切面
@Aspect
public class PreGreetingAspect{
@Before("execution(* greetTo(..))") //<---定義切點和增強類型
public void beforeGreeting(){ //<----增強的橫切邏輯
System.out.println("How are you");
}
}
然后啟動@AspectJ的注解切面驅動就可以了!
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http:
- <A href="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" target=_blank>http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</A>
- http:
- <A href="http://www.springframework.org/schema/aop/spring-aop-2.0.xsd" target=_blank>http://www.springframework.org/schema/aop/spring-aop-2.0.xsd</A>">
- <!--基于@AspectJ切面的驅動器-->
- <aop:aspectj-autoproxy />
- <bean id="waiter" class="com.baobaotao.NaiveWaiter" />
- <bean class="com.baobaotao.aspectj.example.PreGreetingAspect" />
- </beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!--基于@AspectJ切面的驅動器-->
<aop:aspectj-autoproxy />
<bean id="waiter" class="com.baobaotao.NaiveWaiter" />
<bean class="com.baobaotao.aspectj.example.PreGreetingAspect" />
</beans>
四、關于Spring 2.1添加的新功能
1.原來引入一個外面屬性配置文件需要使用以下的方式:
- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <list>
- <!--指定屬性文件地址,可以在這里定義多個屬性文件-->
- <value>classpath:com/baobaotao/place/car.properties</value>
- </list>
- </property>
- <property name="fileEncoding" value="utf-8"/>
- </bean>
-
- <!--引用外部屬性的值,對car屬性進行配置-->
- <bean id="car" class="com.baobaotao.place.Car">
- <property name="brand" value="${brand}" />
- <property name="maxSpeed" value="${maxSpeed}" />
- <property name="price" value="${price}" />
- </bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!--指定屬性文件地址,可以在這里定義多個屬性文件-->
<value>classpath:com/baobaotao/place/car.properties</value>
</list>
</property>
<property name="fileEncoding" value="utf-8"/>
</bean>
<!--引用外部屬性的值,對car屬性進行配置-->
<bean id="car" class="com.baobaotao.place.Car">
<property name="brand" value="${brand}" />
<property name="maxSpeed" value="${maxSpeed}" />
<property name="price" value="${price}" />
</bean>
使用Spring 2.1后,你只需要象下面這樣配置就可以了:
- <context:property-placeholder location=" classpath:com/baobaotao/place/car.properties "/>
<context:property-placeholder location=" classpath:com/baobaotao/place/car.properties "/>
3.注解驅動的Bean注入
大家看看這段E文就OK了,
<context:component-scan>: scans classpath using one or more "include"/"exclude" filters, and automatically registers beans
In essence, this is a third way to define beans (1: classic xml, 2:javaconfig (code), 3:<context:component-scan>, matching on annotations or types)
Default naming strategy is based on short classname of discovered bean
@Component and @Repository annotations, when used, can optionally specify a bean name to use
For filter type "annotation", the value of "expression" attribute should resolve to a Java annotation type
For filter type "assignable", the value of "expression" attribute should resolve to a Java type
For filter type "aspectj", the value of "expression" should be an "type expression" (in Pointcut language, perhaps it could be injected?)
Relevant documentation can be found in preliminary spring 2.1 manual, sections 3.10 and 3.11
In addition, this last JIRA comment for http://www.jetbrains.net/jira/browse/IDEADEV-16886#action_163502 contains two links to articles showing example usage of <context:component-scan>
<context:annotation-config> (described in 3.10 in spring 2.1 manual linked above): allows autowiring to be defined using @Resource or @Autowired annotations.
五、關于Spring 2.5添加的新功能
Spring 2.5繼續對context命名空間進行了擴充,添加了好用而強大的context:load-time-weaver,可以讓我們更方便地應用AspectJ。大家可以看TSS上的這篇文章,它全面講解了Spring 2.5的新特性。
http://www.theserverside.com/tt/articles/article.tss?l=IntrotoSpring25
注:以上大部分代碼來直接引用自 《精通Spring 2.x--企業應用開發精解》
文章來源于:javaeye的stamen