學習Spring筆記七





以spring IOC爲核心,來管理其它框架的重要對象,因爲IOC就是用來管理對象的。








annotation方式整合三大框架  start——————————————————


三個框架都有各自的annotation


struts2  @Action  @Result
spring  @component  @Resource
hibernate  @Entity  


那麼在Spring統一管理當中,如何讓這些註解生效呢?


下面代碼在三大框架整合的基礎上修改


1.spring自己的註解如何生效,applicationContext.xml代碼如下
  <context:component-scan base-package="com.bjsxt"></context:component-scan>   //用了這個掃描器,普通的bean的定義可以不加了,下面的就註釋掉吧
  <!--
  <bean id="userDao" class="com.bjsxt.dao.UserDao">
<property name="sessionFactory" ref="sessionFactory"></property>
  </bean>
  <bean id="userAction" class="com.bjsxt.action.UserAction" scope="prototype">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
  </bean>-->




  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan">
<list>
   <value>com.bjsxt.po</value>
</list>
</property>


<property name="hibernateProperties">  //全局參數
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql://locahost:3306/test</prop>
<prop key="hibernate.connection.username">root</prop>
<prop key="hibernate.connection.password">1234</prop>

<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
  </bean>


  <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemple">
<property name="sessionFactory" ref="sessionFactory"></property>
  </bean>


  <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
  </bean>


  <tx:annotation-driven transaction-manager="txManager"/>


</bean>




2.UserAction.java
@Component
public class UserAction{
private User user;


public User getUser(){
retrun user;
}


public void setUser(User user){
this.user = user;
}

private HibernateTemplete hibernateTemplate;


public HibernateTemplate getHibernateTemplate(){
return hibernateTemplate;
}
@Resource(name="hibernateTemplate")
public void setHibernateTemplate(HibernateTemplate hibernateTemplate){
this.hibernateTemplate = hibernateTemplate;
}

@Transactional
public String add(){
hibernateTemplate.save(user);  
return null; 
}


//這個方法測試時可以關閉或打開,查詢所有
public String findAll(){
List<User> list = hibernateTemplate.find("from User");
for(Iterator iterator = list.iterator(); iterator.hasNext();){
User user = (User) iterator.next();
System.out.println(user.getName()+"--"+user.getId());
}
return null;
}




private String name;
public String findByCondition(){
List<User> list = hibernateTemplate.find("from User u where u.name=?",new Object[]{name});  //逗號後的值對應前面那個問號
for(Iterator iterator = list.iterator();iterator.hasNext();){
User user = (User) iterator.next();
System.out.println(user.getName());
}
return null;
}


public String getName(){
return name;
}


public void setName(String name){
this.name = name;
}
}








3.UserDao.java


@Component
public class UserDao{


private SessionFactory sessionFactory;
public SessionFactory getSessionFactory(){
return sessionFactory;
}

@Resource
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}


public void add(User user){
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}


}




4.導入hibernate關於annotation的三個jar包
  ejb3-persistence.jar  hibernate-annotations.jar   hibernate-commons-annotations.jar




5.在com.bjsxt.po下建立一個User.java
@Entity
@Table(name="t_user")
public class User{
@Id
@GeneratedValue
private Integer id;
private String name;
private String phone;
private Integer age;

public User(String name,String phone,Integer age){
super();
this.name = name;
this.phone = phone;
this.age = age;
}

public User(){
super();
}

public Integer getId(){
return id;
}

public void setId(Integer id){
this.id = id
}

public String getName(){
return name;
}

public void setName(String name){
this.name = name
}

public String getPhone(){
return phone;
}

public void setPhone(String phone){
this.phone = phone;
}

public Integer getAge(){
return age;
}

public void setAge(Integer age){
this.age = age;
}
}






6.Test.java
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);
UserAction userAction = (UserAction)ac.getBean("userAction");
System.out.println(userAction.getClass().getName());
userAction.setName("xiaogao");
userAction.findByCondition();
}
}






7.運行項目,會生成一個表,然後訪問http://localhost:8080/項目名/userAction!add?user.name=xiaogao則會添加數據到數據庫




—————annotationg整合end—————————————





數據庫連接池



怎樣在我們的項目中用連接池及dataSource start————————————————


數據庫連接池,一個班有50個人,不至於一個廁所得有50個坑吧。。小高這比喻。。。數據庫崩潰了不是所有用戶都不能訪問了,而是幾個用戶不能訪問了。就像買火車票,有的人買到


了,有的人沒買到。




數據庫連接池就是,提供你一定數量的連接,大家都從裏面拿數據,當所有連接都被佔用時,再進來的請求在連接
池外面排成隊列等待。這樣的好處是沒有連接的時候不會去冒然創建連接導致報錯,而是等待。有時候我們訪問網站,會出現圈圈等待,那就是稀有資源被佔用,過一會就好了,因爲資


源被釋放,你可以用這資源了。




數據庫連接池的作用:1.穩定 2.提高性能(其實更多的是用戶的體驗高了,服務器本身並沒有減輕負擔,因爲需要維護這個連池,而用戶方面,它進到連接池後就直接可以拿到連


接,就好比去飯店喫飯,你進去後就直接有做好的,不用再等着現做了,快不快?)






實例


1.找到spring-framework-2.5.6\lib\jakarta-commons\下有兩個包是必須的:commons-dbcp.jar和common-pool.jar(如果有c3p0,拷貝c3p0一個包就夠了),把這兩個包拷貝到項目下。




2.在applicationContext.xml添加配置


<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-2.5.xsd
"> 

   <context:component-scan base-package="com.bjsxt"></context:component-scan>

   <bean id="dataSource"  
            class="org.apache.commons.dbcp.BasicDataSource">  
            <property name="driverClassName"  
                value="com.mysql.jdbc.Driver">  
            </property>  
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>  
            <property name="username" value="root"></property>  
            <property name="password" value="1234"></property>
            <property name="maxIdle" value="15"></property>   //連接池內的連接數量
    </bean>  

   <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan">
   <list>
<value>com.bjsxt.po</value>
   </list>
</property>

<property name="dataSource" ref="dataSource"></property>

<property name="hibernateProperties">   //有數據庫連接池了這裏就不用再創建連接了。
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto"  >update</prop>
</props>
</property>
    </bean>

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
    </bean>


    <tx:annotation-driven transaction-manager="txManager" /> 


</beans>








3.Test.java
public static void main(String[] args){
final ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);

//嘗試短時間內,多次sql請求
for(int i=0;i<1000;i++){
new Thread(new Runnable(){
public void run(){
  UserDao dao = (UserDao) ac.getBean("userDao");
  User user = new User("xiaogao","123",12);
  dao.add(user);
}
}).start();
}
}






4.UserDao.java

@Component
public class UserDao {

private SessionFactory  sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Resource
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

public  void add(User  user){
Session  session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
}




5.運行Test.java



做內網項目,用戶也就200來人的,最高峯值也就10、20,用不到池,互聯網公司會用到,人人網、門戶網站,併發量大的。
——————加數據庫連接池end——————————————









——————HibernateTemplate詳解、分頁——————————————————
HibernateTemplate常見方法


用HibernateTemplate實現分頁
  1.不用dao層,直接寫service層,建個com.bjsxt.service包,下面寫UserService接口,內容如下 
public interface UserService{
void add(User user);
void find4page(Integer pagenum,Integer pagesize);
}






  2.建個com.bjsxt.service.impl包,下面寫UserServiceImpl類
@Component
public class UserServiceImpl implements UserService{

private HibernateTemplate hibernateTemplate;//Dao被HibernateTemplate取代了,所以service直接調用HibernateTemplate

public HibernateTemplate getHibernateTemplate(){
return hibernateTemplate;
}

@Resource
public void setHibernateTemplate(HibernateTemplate hibernateTemplate){
this.hibernateTemplate = hibernateTemplate;
}

public void add(User user){
hibernateTemplate.save(user);
}

//分頁用的是hibernateTemplate的回調函數
public void find4page(final Integer pagenum,final Integer pagesize){  

List<User> list=(List<User>) hibernateTemplate.execute(new HibernateCallback(){
public Object doInHibernate(Session session) throws HibernateException,
SQLException{
Query query = session.createQuery("from User");
 query.setFirstResult((pagenum-1)*pagesize);
 query.setMaxResults(pagesize);
 return query.list();
}
});
}
}


   


封裝的目的,不變的保留,變的通過參數傳入。


3.希望能運行出來。。。講的太亂了,這一句,那一句的,使用還沒講明白呢又去講原理。0033零零散散。


———————HibernateTemplate分頁end———————————————————————









—————————————事務—————————————————————————————


annotation方式開啓事務
只要給我們的類前面加一個annotation的註解:transaction,我們的方法就具備了事務。說白了事務就是begintransaction和comminttransaction。這兩行代碼在方法前後執行,就構成了一個事務的嚴格的邊界。


事務********
begin transaction可以開始一個事務,commit transaction可以提交這個事務。如果在此次執行中有錯誤,或想取消,可以使用RollbackTrans回滾事務,則在開始事務後的操作會被全部取消。 begin transaction的後面必須帶commit transaction或 rollback transaction其中的一個
**************


但這種方法的問題是,想要一個事務,就需要在這個方法前加一個@Transactional。service層有很多的方法,action層也有很多的方法。每個頭上都加很彆扭。基本上有一個約定的規則:把事務的邊界定義到service層。(action負責C,傳遞信息和跳轉,所以不要在action層處理過多的邏輯,所以不要把@Transaction寫在action層。)。用切面的形式在service層做事務管理。


具體實例:
1.在applicationContext.xml中如下寫

<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-2.5.xsd
"> 

<context:component-scan base-package="com.bjsxt"></context:component-scan>

<bean id="dataSource"  
            class="org.apache.commons.dbcp.BasicDataSource">  
            <property name="driverClassName"  
                value="com.mysql.jdbc.Driver">  
            </property>  
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>  
            <property name="username" value="root"></property>  
            <property name="password" value="1234"></property>
            <property name="maxIdle" value="15"></property>
            <!-- 
            maxActive
minIdle 
maxIdle 
initialSize 
             -->
    </bean>  

<bean  id="sessionFactory"  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
<property name="packagesToScan" >
<list>
<value>com.bjsxt.po</value>
</list>
</property>

<property name="dataSource" ref="dataSource"></property>

<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto"  >update</prop>
</props>
</property>
</bean>


<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>

<!-- 
txManager 管理   事務的開啓  和關閉
-->

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >    //這裏的ID是提供給下面的transaction-manager事務管理器的
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 
annotation  方式的 事務 也是 使用 代理模式。 
在需要事務的方法前後執行代碼。    類似around 通知類型
-->

<tx:annotation-driven transaction-manager="txManager" /> 


<aop:config>
<aop:pointcut expression="execution(public * com.bjsxt.service.impl.*.*(..))" id="bussinessService"  />//這個切面的含義是切割所有service的實現類!!!!!!!!***********切面影響的是一個層。
<aop:advisor advice-ref="txAdvice" pointcut-ref="bussinessService" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager" > //transaction-manager是事務管理器,必須要拿過來
<tx:attributes>
<tx:method name="find*" read-only="true" propagation="NOT_SUPPORTED" />   //對方法進行分類,需要事務的和不需要事務的方法分開,這裏定義的是一個規則,以find開頭的,設置爲只讀模式read-only="true",不需要事務propagation="NOT_SUPPORTED"
<tx:method name="add*" propagation="REQUIRED" />  //以add開頭的方法需要事務 方法的定義一定要按規則,不解會切不到。在公司工作中,如果要添加方法,先要看人家之前這裏怎麼定義的,要按人家的規則走。
<tx:method name="del*" propagation="REQUIRED" />  //以del開頭的方法需要事務
<tx:method name="update*" propagation="REQUIRED" />  //以update開頭的方法需要事務
</tx:attributes>
</tx:advice>
</beans>


配置好了這個後,即使我們的方法不加@Transaction,方法也可以正確執行。因爲這些方法已經默認有事務了。


——————————————題外
拿到一個項目,先看web.xml,配置了哪些filter,因爲filter和servlet它們攔截的經常是/*,所以先看一下,你的請求會被哪些關鍵的過濾器攔截。接着再看AOP(applicationContext.xml),看看你的類會被哪些切面切到。這些都是對你的代碼有深層影響的東西。別一上來就增刪查改就寫。




2.第一步是已經切面了,切完後做什麼。。。tx是切面的簡寫
——————————————————————————————————————



2.Test.java
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);

//怎麼看一個方法有沒有事務=看它有沒有代理類
UserService service = (UserService)ac.getBean("userServiceImpl"); //配置文件中沒有寫bean,但是我們在userServiceImpl前加@Component了。如果我們獲取出來的類不是代理類,它前後沒有植入功能,它的前面和後面就不會切到
System.out.println(service.getClass().getName());   //運行此方法,結果是$Proxy11,這是代理類的格式,說明是代理類。如果打印出來的是原生態的Name,那說明不是代理類。
User user = new User();
user.setName("123123123");
service.add(user);  //在上面那行確認了service類已經切到了,可以開始執行service的add方法了。
}
}




3.UserService.java
public interface UserService {

void add(User user);

void find4page(Integer pagenum, Integer pagesize);

}






4.UserServiceImpl.java
@Component
public class UserServiceImpl  implements UserService {

private HibernateTemplate  hibernateTemplate;
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
@Resource
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}

public void add(User user) {
hibernateTemplate.save(user);
}
public void find4page(final  Integer pagenum, final Integer pagesize) {
// java 設計者:   內外一致性
List<User>  list =(List<User>) hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException,
SQLException {
// TODO Auto-generated method stub
Query  query =session.createQuery("from User");
query.setFirstResult((pagenum-1)*pagesize);
query.setMaxResults(pagesize);
return query.list();
}
});
// 模板方法模式       重用代碼  
}
}






5.運行Test.java測試




———線程安全(衝突)解決方案 start———————————————————


1.ThreadLocal是爲了解決線程併發。


線程安全問題:多個線程訪問同樣一個數據,這是線程安全的前提,兩個人去搶一個東西,纔會造成衝突。線程不安全的前提是:併發!

什麼地方線程不安全呢?servlet(單例多線程),一個實例支撐多個線程對它的方法的調用。如果使用servlet的成員變量來存儲值,那麼這個場景會觸發線程衝突。因爲單例是單份的數據塊,你一個線程對它進行刪除,另一個線程又對它進行添加,再來一個線程對它進行修改。當線程過多的時候 ,數據肯定會錯亂。衝突的後果是:髒數據。數據變得不穩定、不規律(本來數據應該從1變到2,結果還是1)衝突的原因是單例多線程。衝突的前提是:併發!解決衝突的思路是:ThreadLocal,它的解決辦法是每一個線程一個數據塊,大家不掙不搶。我們經常叫ThreadLocal線程局部變量。爲當前線程綁定一個數據塊(一個線程有一個小‘倉庫數據塊’來存儲相應的值),從而解決線程衝突(三個小孩,一人一個蘋果,還打架嗎?)。
但是ThreadLocal解決衝突是有成本的,是一種空間換時間的思路。利用多餘的空間換來了不衝突。本來1000個線程一個數據,這1000個線程得排隊,現在是1000個線程,1000個數據塊,不用排隊,用戶體驗好了,但是空間佔用多了。這種方式是空間換時間。






2.還有一種解決衝突的辦法:鎖!synchronized鎖住以後,只有一個線程能進入到當前方法。剩下的線程都在排隊。每次只一個線程進來,這樣的話有很多線程在排隊。這種方式是用時間換空間。




兩種方案視情況,不同的需要選用不同的方案,如果內存小就空間優先,如果對時間有要求,就時間優先。




線程安全(衝突)解決方案end ————————————————






—————用ThreadLocal模式管理session—————————
ThreadLocal是一個線程綁定一個數據塊。用它來管理Session是指爲一個線程綁定一個Session對象,統一用這個Session對象。下一個線程也有自己的Session,每個Session都有自己的對象,因爲不會造成衝突。一個線程綁定了一個Session對象後,在這個線程的任何一個地方,都可以把這個Session拿出來。所以括大了Session的生命週期。使用ThrealLocal管理Session對象後擴大了Session的生命週期。造成了一個結果就是Session不需要在一個方法內定義或是關閉了。因爲我們可以把它放在一個線程裏,讓它在整個線程裏有效。讓這個Session不至於只在一個方法內有效。


一個線程可以調用很多個方法(有多個連接點),方法調用相互之間傳參數、返回值。兩個方法都需要創建Session,那麼這個線程就可以和一個Session對象綁定,從而這些方法使用一個Session。



爲什麼要擴大Session生命週期?它能解決什麼問題?
在hibernate中,1+N問題(一條SQL語句帶來多條SQL語句執行),產生這個問題的原因是lazy="false",不懶加載,立即加載。解決1+N問題的辦法是:把lazy="true"。但是lazy="true"以後,頁面上使用代理對象的時候發現Session已經閉關了。所以這時候引出了擴大Session生命週期問題。


那怎麼擴大呢?什麼時候定義Session、關閉Session?最終引出了使用ThreadLocal來管理Session。


結論:1+N問題用ThreadLocal解決,也解決了1+N帶來的所有問題





如果讓我們自己來實現ThreadLocal怎麼實現呢?


1.建立一個包com.bjsxt.filter,在它下面建立OpenSessionInViewFilter.java
public class OpenSessionInViewFilter implements Filter{

public void destroy(){
}

public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException,ServletException{
Session session = sessionFactory.openSession(); //這定義的Session別人是不能用的,因爲是局部變量。但是如果藉助ThreadLocal就可以讓別的方法也能使用此
Session。

HibUtil.threadLocal.set(session);  //這步置關重要!是把創建的session放到HibUtil的的threadLocal中。
arg2.doFilter(arg0,arg1); //此時Session擴大到請求和響應,從一個請求來服務器開始,到響應返回以後。後臺執行的所有流程都是在Session生命週期內。
HibUtil.threadLocal.remove();
session.close();
}
public void init(FilterConfig arg0) throws ServletException{
}

}




2.定義一個util包,下面定義一個類HibUtil.java(藉助ThreadLocal讓Session生命週期變長)
public class HibUtil{

public static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

public static Session getSession(){
Session session = threadLocal.get();
if(session == null){
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}


public static void main(String[] args){
HibUtil.getSession();
HibUtil.getSession();  //一個線程中獲取兩次session,這兩個拿出來的是一個Session,都是綁定在線程中的那個session,而且這個Session什麼時候關不需要管
}
}




3.運行HibUtil.java測試








——————和自己寫ThreadLocal管理Session作用相同的:Spring的OpenSessionInviewFilter的用法————————————


**OpenSessionInviewFilter是spring提供的一個針對Hibernate的支持類,和我們上面寫的代碼的作用一樣。主要意思是在發起一個頁面請求時打開Hibernate的Session,一直保持這個Session,直到這個請求結束,具體是通過一個Filter來實現的************


1.把如下代碼配置到struts過濾器之前
<!--配置Spring自動管理Session,要配置到struts過濾器之前-->
<filter>
<filter-name>hibernateSessionFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInviewFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>hibernateSessionFilter</filter-name>
<url-pattern>*.action</url-pattern>   //最好改成*.action,只攔截action,只攔截對後臺發起的訪問,在這個時候打開session是有必要的。如果只是訪問html就打開一Session會造成浪費,這樣的配置會浪費性能。
</filter-mapping>


**使用spring的hibernateSessionFilter,就把session的生命週期放在了filter位置,把事務開和關放在了service層









********題外,以後的環境模型架子*********************************
applicationContext.xml
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 

<context:component-scan base-package="com.bjsxt"></context:component-scan>

<bean id="dataSource"         //有連接池
            class="org.apache.commons.dbcp.BasicDataSource">  
            <property name="driverClassName"  
                value="com.mysql.jdbc.Driver">  
            </property>  
            <property name="url" value="jdbc:mysql://localhost:3306/test"></property>  
            <property name="username" value="root"></property>  
            <property name="password" value="1234"></property>
            <property name="maxIdle" value="15"></property>
</bean>  

<bean  id="sessionFactory"  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >    //有sessionFactory

<property name="packagesToScan" >     //有sessionFactory中的包掃描器
<list>
<value>com.bjsxt.po</value>
</list>
</property>

<property name="dataSource" ref="dataSource"></property>

<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto"  >update</prop>
</props>
</property>
</bean>

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate" >   //有HibernateTemplate
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >   //有事務
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>

<tx:annotation-driven transaction-manager="txManager" />     //annotation式的事務



<aop:config>    //AOP
<aop:pointcut expression="execution(public * com.bjsxt.service.impl.*.*(..))" id="bussinessService" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="bussinessService" />
</aop:config>


<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true" propagation="NOT_SUPPORTED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" /> 
</tx:attributes>
</tx:advice>
</beans>




這個applicationContext.xml配置文件寫好後就不需要修改了,只有以下幾點需要注意


再添加配置就是添加struts2.xml中的action,或spring的bean的annotation配置(不需要改配置文件) ,hibernate的entity(po)不需要改配置文件




在拿到項目後,也要先看看,首先看數據庫連接和本機一樣否,aop的切面是否和你的包結構一樣。仔細審查配置文件的功能是否符合當前項目。


struts使用配置文件的好處是能看清誰往哪跳,邏輯比較一目瞭然。spring和hibernate使用annotation,只把固定的寫在applicationContext.xml中。
************************************************************************************






題外————
在依賴注入時,當屬性是集合類型時,如何注入值??(如action中的屬性是數組類型,String[],在applicationContext.xml中怎麼配置才能注入值呢?)


代碼實例
1.UserDao.java代碼如下
public class UserDao{
private String[] ccc;
public String[] getCcc(){
return ccc;
}

public void setCcc(String[] ccc){
this.ccc = ccc;
}

public List<String> list;

private Set<String> set;
private Map<String, String> map;
private Properties pp;

/**
...這些屬性的set、get方法
**/

public UserDao(){
System.out.println("init......");
}

public void add(){
System.out.println("add......");
}
}




2.applicationContext.xml代碼如下
<bean id="userDao" class="com.bjsxt.dao.UserDao">
<property name="ccc">    //這樣就賦與了cc這個數組屬性三個值,每個property對應了bean的class中的類的一個屬性
<list>
<value>111</value>
<value>222</value>
<value>333</value>
</list>
</property>
<property name="list">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="set">
<set>
<value>sss</value>
<value>qqq</value>
<value>www</value>
</set>
</property>
<property name="map">
<map>
<entry>
<key><value>name</value></key>
<value>xiaogao</value>
</entry>
</map>
</property>
<property name="pp">
<props>
<prop key="cacheProvider">ehcache</prop>  //ehcache是隨便寫的字符串,給pp賦的值
</props>
</property>
</bean>






3.加一個main方法來測試
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);

UserDao dao = (UserDao) ac.getBean("userDao");
dao.add();
}
}




4.在dao.add()上打斷點進行debug調試


題外end——————————————————————————————————

SPRING END——————————————————————————————

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章