Spring 學(xué)習(xí)
1.spring屬性的注入配置
- 1. 屬性的注入配置
Bean文件的配置,即為bean的各屬性賦值
<bean id="sone" class="edu.yzu.entity.Student" init-method="initialMethod" parent="sbean" >
<!—- init-method指定了該bean類初始化后用來驗(yàn)證屬性是否合法,該方法會(huì)在屬性設(shè)置結(jié)束后調(diào)用 ,
Parent是指本bean中的一些屬性如果沒有初始化則會(huì)以sbean中的相同屬性名的對應(yīng)值來初始化--!>
<property name="id" value="10002" />
<property name="name" value="Rose" />
<property name="sex" value="boy" />
<property name="age" value="23" />
<property name="birthday" value="1980-10-24" />
<property name="emails">
<list>
<value>123@qq.com</value>
<value>456@sina.com</value>
<value>789@163.com</value>
</list>
</property>
<property name="phones">
//list或者數(shù)組類型的屬性注入
<list>
<value>13657164847</value>
<value>15901083941</value>
<value>13797502137</value>
</list>
</property>
<property name="scores">
//為map指定 key value屬性指定一般類型,key-ref value-ref指定的是bean引用
<map>
<entry key="math" value="97" />
<entry key="chinese" value="96" />
<entry key="englist" value="92" />
</map>
</property>
<property name="classmates">
//set類型的屬性注入
<set>
<ref local="sone" />
<!-- 表時(shí)此值并非String int 等原始類型,local指明這個(gè)值是本配置文件的一個(gè)bean -à
<ref local="myself" />
</set>
</property>
</bean>
- 非自動(dòng)類型轉(zhuǎn)換
對bean屬性的注入過程中,如果一些類型不能注入,則可以類型轉(zhuǎn)換,自定義轉(zhuǎn)換該類型的轉(zhuǎn)換器,如上面的birthday屬性是日期性的,spring 不能自動(dòng)注入該類型,則自定義轉(zhuǎn)換器如下:
public class myDateEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
Date date = format.parse(text);
setValue(date);
} catch (ParseException e) {
e.printStackTrace();
new IllegalAccessException(e.getMessage());
}
}
}
配置文件如下 :只要這樣配置后spring 遇到j(luò)ava.util.Date類型后會(huì)自動(dòng)調(diào)用上面的轉(zhuǎn)換器,注入bean屬性
<bean id="myeditor"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<bean id="dateEditor" class="edu.yzu.editor.myDateEditor" />
</entry>
</map>
</property>
</bean>
2.spring非自動(dòng)類型轉(zhuǎn)換
對bean屬性的注入過程中,如果一些類型不能注入,則可以類型轉(zhuǎn)換,自定義轉(zhuǎn)換該類型的轉(zhuǎn)換器,如上面的birthday屬性是日期性的,spring 不能自動(dòng)注入該類型,則自定義轉(zhuǎn)換器如下:
public class myDateEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
Date date = format.parse(text);
setValue(date);
} catch (ParseException e) {
e.printStackTrace();
new IllegalAccessException(e.getMessage());
}
}
}
3.spring中面向切面的使用
- BeanPostProcessor接口的使用
BeanPostProcessor接口用在bean生成后將放入ApplicationContext前進(jìn)行一些必要的處理,它有兩個(gè)方法,分別在調(diào)用bean配置的init-method前后執(zhí)行(如果配置了的話),本接口的實(shí)現(xiàn)類常常結(jié)合動(dòng)態(tài)代理生成bean的代理類型:
class MyProxyClass {
private Object target;
public MyProxyClass(Object target) {
this.target = target;
}
public Object getNewProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
System.out.println("you can do something here!!");
Object obj = method.invoke(target, args);
System.out.println("you can do something here!!");
return obj;
}
});
}
}
接口使用如下,接口使用如下,一般只要在postProcessAfterInitialization里面配置后即可(事實(shí)上這在實(shí)際開發(fā)中很少使用,一般會(huì)使用spring提供的組件,但其底層是使用這些的)
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String id)
throws BeansException {
//參數(shù)Object 為生成的bean id 為該bean在配置文件中的id,這里我們一該用動(dòng)態(tài)代理來生成一個(gè)代理對象返回
return new MyProxyClass(bean).getNewProxy();
}
public Object postProcessBeforeInitialization(Object bean, String id)
throws BeansException {
return bean;
}
}
配置如下:
<bean id="myprocessor" class="edu.yzu.filter.MyBeanPostProcessor" />
如上配置后spring 會(huì)自動(dòng)為每個(gè)生成的bean生成相應(yīng)的代理,如上代理的的效果為在調(diào)用每個(gè)方法找對應(yīng)此bean的id,,,我們可以使用動(dòng)態(tài)代理來生成
- 對bean中方法的方法的攔截(既自定義的Advice)共有四種,分別為四個(gè)接口,繼承此四個(gè)接口后分別實(shí)現(xiàn)對應(yīng)的方法:
MethodBeforeAdvice(在方法調(diào)用之前)
public void before(Method method, Object[] args, Object target)
throws Throwable {
//要在方法調(diào)用之前執(zhí)行的操作
}
MethodInterceptor (在方法調(diào)用之前之后都可以用此接口中的一個(gè)方法得到)
AfterReturningAdvice(在方法返回以后)
public void afterReturning(Object returnValue, Method method, Object[] args,
Object targer) throws Throwable {
//在方法調(diào)用之后 要執(zhí)行的操作
}
ThrowsAdvice(在方法拋出異常以后會(huì)攔截)
public void afterThrowing(Exception e) {
Session session=HibernateSessionFactory.getSessionFactory().getCurrentSession();
session.getTransaction().rollback();
}
注意:ThrowsAdvice接口中沒有任何方法,但是使用此接口必須給出的方法簽名為:afterThrowing,它可以重載多次,當(dāng)相應(yīng)的異常發(fā)生后調(diào)用對應(yīng)的處理方法
使用:在配置文件中配置自定義的Advice,比如我有一個(gè) TranstionManager類,它用來控制事務(wù),實(shí)現(xiàn)了MethodInterceptor,如下!
public class TranstionManager implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
Session session = HibernateSessionFactory.getSessionFactory()
.getCurrentSession();
Transaction trans = session.getTransaction();
trans.begin();
Object obj = invocation.proceed();
trans.commit();
return obj;
}
}
文件的配置如下:
<bean id="transtionmanager" class="edu.yzu.filter.TranstionManager"/>
另外有一個(gè)bean即為攔截的目標(biāo)對象,為其生成代理對象,該bean的配置如下:
<bean id="userDao" class="edu.yzu.dao.impl.UserDaoImpl"/>
<bean id="userBiz" class="edu.yzu.biz.impl.UserBizImpl">
<property name="userDao">
<ref local="userDao"/>//將userDao注入到到UserBizImpl中
</property>
</bean>
下面為userBiz生成代理對象的bean使用時(shí)用ApplicationContext對象實(shí)例applicationContext調(diào)用代理對象的方法為:applicationContext.getBean(“userBizImpl”);
<bean id="userBizImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="userBiz"/>//指定給哪個(gè)目標(biāo)對象建立代理
</property>
<property name="interceptorNames">
<list>
<value>transtionmanager</value>
//使用的Advice, 可以配置多個(gè)
</list>
</property>
<property name="interfaces">
<list>
<value>edu.yzu.biz.UserBiz</value>
//指定要代理目標(biāo)對象的哪個(gè)的接口
</list>
</property>
</bean>
(上面是為實(shí)現(xiàn)接口的類生成代理) 缺點(diǎn):一旦為一個(gè)bean指定代理,則bean中的所有方法都會(huì)被代理,不能指定為特定的方法指定代理,沒有體現(xiàn)面向切面的特點(diǎn)!優(yōu)點(diǎn),依然可以拿到代理前的bean對象。如果沒有實(shí)現(xiàn)任何接口,則不必要加name=”interfaces” 的項(xiàng),但要加<property name="proxyTargetClass">
<value>true</value>
</property>表示這個(gè)bean沒有實(shí)現(xiàn)任何接口,spring為它生成它的子類(cglib實(shí)現(xiàn))
- 切面=切入點(diǎn)+切入內(nèi)容。既為:aspect=pointcut+advice spring 中切面用advisor表示,可以在配置文件中配置。切入的內(nèi)容即為我們自定義的類型,它實(shí)現(xiàn)四個(gè)接口的的任何一個(gè)。切入點(diǎn)即為要切入內(nèi)容的目標(biāo)類型的方法:由此可知切面的配置也要配置這兩項(xiàng)!
l 為一個(gè)bean配置一個(gè)advisor ,一個(gè)advisor里面只能有一個(gè)advice,但是可以給此advisor指定幾個(gè)切入點(diǎn),方法如下:
<bean id="myadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<ref local="transtionmanager"/>
</property>
<property name="mappedNames">
<list>
<value>addProduct</value>
<value>deleteProductById</value>
<value>getAllProducts</value>
<value>getProduct</value>
<value>getProducts</value>
<value>updateProduct</value>
</list>
</property>
</bean>
這個(gè)Advisor只指定的advice為transtionmanager 為切入的內(nèi)容,切入點(diǎn)為list只的幾個(gè)方法名,既所代理的bean中,只有方法名相同的才能被切入。這正是面向切面的思想所在,advisor用法如下:
<bean id="productBizImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="productBiz"/>
</property>
<property name="interceptorNames">
<list>
<value>myadvisor</value>
<value>exceptionadvice</value>//這個(gè)是沒有包裝的advice,配置如下:
//<bean id="exceptionadvice" class="edu.yzu.filter.ExceptionFilter"/>
</list>
</property>
<property name="interfaces">
<list>
<value>edu.yzu.biz.ProductBiz</value>
</list>
</property>
</bean>
這樣做的好處體現(xiàn)了面向切面的思想,既給指定的切入點(diǎn)切入想要執(zhí)行的內(nèi)容。
下面是為多個(gè)bean指定多個(gè)advisor的方法,似乎也是最為常用的。
l 第一種:為多個(gè)bean同時(shí)指定多個(gè)advisor
Advisor配置不變,如下
<bean id="myadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<ref local="transtionmanager"/>
</property>
<property name="mappedNames">
<list>
<value>addProduct</value>
<value>deleteProductById</value>
<value>getAllProducts</value>
<value>getProduct</value>
<value>getProducts</value>
<value>updateProduct</value>
</list>
</property>
</bean>
指定代理的目標(biāo)對象的配置如下,既為哪些目標(biāo)bean生成代理
<bean id="autoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>myadvisor</value>
<value>exceptionadvisor</value>
//自定義的advisor
</list>
</property>
<property name="beanNames">
<list>
<value>userBiz</value>
<value>productBiz</value>
//生成代理的目標(biāo)對象
</list>
</property>
</bean>
優(yōu)點(diǎn):可以同時(shí)為多個(gè)bean指定多個(gè)advisor。不足,因?yàn)槭亲詣?dòng)的為指定的bean生成代理,所以不能再得到原來的bean,只能拿到代理后的bean對象
l 第二種:為多個(gè)bean同時(shí)指定多個(gè)advisor
完整配置如下:
<bean id="userBiz" class="edu.yzu.biz.impl.UserBizImpl">
<property name="userDao">
<bean id="userDao" class="edu.yzu.dao.impl.UserDaoImpl" />
</property>
</bean>
<bean id="productBiz" class="edu.yzu.biz.impl.ProductBizImpl">
<property name="productDao">
<bean id="productDao" class="edu.yzu.dao.impl.ProductDaoImpl" />
</property>
</bean>
<bean id="myadvisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean id="transtionmanager" class="edu.yzu.filter.TranstionManager" />
</property>
<property name="mappedNames">
<list>
<value>addProduct</value>
<value>deleteProductById</value>
<value>getAllProducts</value>
<value>getProduct</value>
<value>getProducts</value>
<value>updateProduct</value>
</list>
</property>
</bean>
<bean id="exceptionadvice"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice">
<bean id="exadvice" class="edu.yzu.filter.ExceptionFilter" />
</property>
<property name="mappedNames">
<list>
<value>addProduct</value>
<value>deleteProductById</value>
<value>getAllProducts</value>
<value>getProduct</value>
<value>getProducts</value>
<value>updateProduct</value>
</list>
</property>
</bean>
<bean id="defaultautoproxy"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
優(yōu)點(diǎn),可以同時(shí)多個(gè)bean指定多個(gè),advisor,缺點(diǎn):可控性差。會(huì)為整個(gè)配置文件的所有的非advisor的bean都指定所有的advisor。注意事項(xiàng),不必要的bean不要放在一個(gè)配置文件中,或者放在另外一個(gè)bean的內(nèi)部,但是這樣的bean對外界不可見,即不可用ApplicationContext的對象通過getBean得到!(實(shí)際用得不多)
6.spring中事務(wù)管理
聲明式的事務(wù)管理(Declarative transaction management):
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@localhost:1521:XE</value>
</property>
<property name="username">
<value>rose</value>
</property>
<property name="password">
<value>aier</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.jdbc.batch_size">15</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/kettas/shops/entity/Entity.hbm.xml</value>
</list>
</property>
</bean>
<bean id="hibernatetemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--
dao的bean
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-->
<bean id="userDao" class="edu.yzu.shops.dao.impl.UserDaoImpl">
<property name="hibernateTemplate">
<ref local="hibernatetemplate" />
</property>
</bean>
<!--
biz的配置
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-->
<bean id="userBiz" class="edu.yzu.shops.biz.impl.UserBizImpl">
<property name="userDao">
<ref local="userDao" />
</property>
</bean>
<!--
事物控制
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="update*">
PROPAGATION_REQUIRED,-Exception
</prop>
<prop key="delete*">
PROPAGATION_REQUIRED,-Exception
</prop>
</props>
</property>
</bean>
<!-- 有兩種方式可以給一個(gè)bean加上事務(wù)控制,一種為自動(dòng)創(chuàng)建。
另一種是指明創(chuàng)建 .第一種為:-->
<bean id="autoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>userBiz</value>
<value>productBiz</value>
<value>orderBiz</value>
<value>orderItemBiz</value>
<value>categoryBiz</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 第二種方法為下面,顯然表比較少時(shí)用第二種可以,但是當(dāng)表比較多時(shí)顯然第一種更合適。 -->
<bean id="userBizProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref bean="userBiz" />
</property>
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<!-- 下面的設(shè)置表時(shí)要代理的不是類本身,而是其實(shí)現(xiàn)的接口 -->
<property name="proxyTargetClass">
<value>false</value>
</property>
<property name="proxyInterfaces">
<list>
<value>edu.yzu.biz.UserBiz</value>
</list>
</property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="update*">
PROPAGATION_REQUIRED,-Exception
</prop>
<prop key="delete*">
PROPAGATION_REQUIRED,-Exception
</prop>
</props>
</property>
</bean>
<!--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-->
1.
2.
3.
4.
5.
6.
7. <bean
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置事務(wù)管理器 -->
<property>
<ref bean="transactionManager" />
</property>
<!-- 此屬性指定目標(biāo)類本身是否是代理的對象,如果目標(biāo)類沒有實(shí)現(xiàn)任何類,就設(shè)為true代表自己 -->
<property>
<value>false</value>
</property>
<property>
<value> com.test.service.userManageService</value>
</property>
<!-- 目標(biāo)bean -->
<property>
<ref bean="userManageService"/>
</property>
<!-- 配置事務(wù)屬性 -->
<property>
<props>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
利用繼承的思想簡化配置,適合相對比較多的模塊時(shí)使用。
<bean id="transactionBase"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
lazy-init="true" abstract="true">
<!-- 配置事務(wù)管理器 -->
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<!-- 配置事務(wù)屬性 -->
<property name="transactionAttributes">
<props>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
8.<bean
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
lazy-init="true" abstract="true">
<!-- 配置事務(wù)管理器 -->
<property>
<ref bean="transactionManager" />
</property>
<!-- 配置事務(wù)屬性 -->
<property>
<props>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
而具體的模塊可以簡單的這樣配置。只要指明它的parent(父類)就可以了。父類一般把a(bǔ)bstract="true",因?yàn)樵谌萜骷虞d的時(shí)候不需要初始化,等到用的時(shí)候再有它的子類調(diào)用的時(shí)候,再去初始化。
Java代碼
<bean id="userManageServiceProxy" parent="transactionBase" >
<property name="target">
<ref bean="userBiz"/>
</property>
</bean> <bean parent="transactionBase" >
<property>
<ref bean="userManageService"/>
</property>
</bean>
8.DWR與spring的整合簡單使用
- 文件的配置。在web.xml中配置dwr的攔截器,為一個(gè)Servlet,配置如下:
<servlet>
<servlet-name>dwrServlet</servlet-name>
<servlet-class>
org.directwebremoting.servlet.DwrServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwrServlet</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
- 在dwr.xml文件中的配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">
<dwr>
<allow>
<create javascript="JTestBean" creator="new">
<param name="class" value="edu.yzu.dwr.TestBean"/>
</create>
<convert converter="bean" match="edu.yzu.dwr.Student"/>
<!--
<convert converter="bean" match="edu.yzu.dwr.Teacher"/>
若是在方法簽名或者返回類型中用到了自定義類型,則要加上這一句,即給自定義類型一個(gè)轉(zhuǎn)換器,在客戶端會(huì)自動(dòng)被轉(zhuǎn)換為js對象 -->
</allow>
<!—下面也有必要配置一下,即當(dāng)所使用的方法簽名有用到泛型集合時(shí)要指定(往往不配置也沒沒有什么錯(cuò)誤)-- >
<signatures>
<![CDATA[
import java.util.* ;
import edu.yzu.entity.*.*;
public List<User> queryAllUsers() ;
]]>
</signatures>
- 在所使用的頁面引用dwr動(dòng)態(tài)生成的js文件!
<script src="/ajax/dwr/interface/JTestBean.js"></script>
<script src="/ajax/dwr/engine.js"></script>
如果有必要還可以引用dwr提供的一個(gè)util.js的工具包
- dwr整合spring的配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">
<!-- dwr與spring的整合
create標(biāo)簽的creator值為spring表時(shí)dwr在不創(chuàng)建對象,而是使用
spring托管的對象。
它的param標(biāo)簽的name屬性為beanName,value屬性的值與spring中bean
的id值對應(yīng)。
-->
<dwr>
<allow>
<create javascript="userBiz" creator="spring">
<param name="beanName" value="userBiz" />
</create>
<convert converter="bean" match="edu.yzu.shops.entity.User" />
</allow>
</dwr>
posted on 2011-11-16 01:16 Steven_bot 閱讀(544) 評論(0) 編輯 收藏 所屬分類: study logger