Java後臺—Spring

1. Spring介紹

Spring的核心是控制反轉(IoC)和麪向切面(AoP)。
總共分爲三層結構:

  • WEB層:Spring MVC
  • 業務層:Bean管理(IOC)
  • 持久層:Spring的JDBC模板,ORM模板用於整個其他的持久層框架
    Spring 的Bean屬性注入:

1.1 Sping架構

這裏寫圖片描述

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉 (IOC) 模式將應用程序的配置和依賴性規範與實際的應用程序代碼分開。

  • Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。
    Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何對象支持 AOP。Spring - - AOP 模塊爲基於 Spring 的應用程序中的對象提供了事務管理服務。通過使用 Spring AOP,不用依賴 EJB 組件,就可以將聲明性事務管理集成到應用程序中。

  • Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,並且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。

  • Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關係工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。

  • Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上,爲基於 Web 的應用程序提供了上下文。所以,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作。

  • Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口,MVC 框架變成爲高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。

1.2 Spring配置

  1. 依賴包的注入
    Alt text
  2. 引入相關的配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    >
    //引入約束

 <!--將User對象交給Spring容器管理-->
    <!--Bean元素;使用該元素描述需要spring容器管理的對象-->
    <bean name="user" class="cn.raine.bean.User"></bean>
</beans>

1.3 Spring的工廠 (容器)

ApplicationContextBeanFactory(在內存資源少的時候使用已過時)
區別
BeanFactory :是在 getBean 的時候纔會生成類的實例.
ApplicationContext :在加載 applicationContext.xml(容器啓動)時候就會創建.
獲取容器

 //創建容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User u = (User) ac.getBean("user");
        System.out.print(u);

1.4 Spring相關配置屬性

  • id屬性:Bean 起個名字. 在約束中採用 ID 的約束:唯一. 必須以字母開始,可以使用字母、數字、連字符、 下劃線、句話、冒號 id:不能出現特殊字符.
  • name屬性:Bean 起個名字. 沒有采用 ID 的約束. name:出現特殊字符.如果<bean>沒有 id 的話 , name 可 以當做 id 使用.
  • scop屬性
  • singleton : 默認值,單例的
  • prototype: 多例的

1.4.1 Bean的生命週期

通過配置<bean>標籤上的init-method 作爲 Bean 的初始化的時候執行的方法,配置 destroy-method作爲 Bean 的銷燬的時候執行的方法。 銷燬方法想要執行,需要是單例創建的 Bean 而且在工廠關閉的時候,Bean 纔會被銷燬

1. 5 Spring的注入

  1. Spring的bean的屬性注入
  • 構造方法的注入方式
<!-- 第一種:構造方法的方式 -->  
<bean id="car" class="cn.itcast.spring.demo4.Car"> 
  <constructor-arg name="name" value=" 保時捷 "/>   
  <constructor-arg name="price" value="1000000"/> 
 </bean> 
  • set方法的注入屬性
<!-- 第二種:set 方法的方式 -->  
<bean id="car2" class="cn.itcast.spring.demo4.Car2"> 
  <property name="name" value=" 奇瑞 QQ"/>   
  <property name="price" value="40000"/>  
  </bean> 
  1. 對象類型的注入
 <!-- 注入對象類型的屬性 -->  
 <bean id="person" class="cn.itcast.spring.demo4.Person"> 
  <property name="name" value=" 會希 "/>   
  <!-- ref 屬性:引用另一個 bean 的 id 或 name -->   
  <property name="car2" ref="car2"/> 
   </bean> 
  1. 複雜類型的注入
 <!--複雜類型的注入-->
    <bean name="cb" class="cn.raine.injection.CollectionBean">
        <property name="arr">
            <list>
                <value>會希</value>
                <value>哈哈</value>
            </list>
        </property>
        <property name="list">
            <list>
                <value>javck</value>
                <value>jerry</value>
                <ref bean="user2"></ref>
            </list>
        </property>
    </bean>

構造函數注入的時候

//確定使用哪個構造函數
<constructor-arg name="name" index="0" type="java.lang.Interger"/>

listener是spring web 包

2. AOP

2.1 使用註解配置Spring

頭部約束

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

    >

xml中寫入

     <!--指定掃描cn.raine.bean下的所有類的註解
    注意:掃描包時,會掃描指定包下所有的子包
    -->
    <context:component-scan base-package="cn.raine.bean"></context:component-scan>

代碼註解

//將對象注入到容器
Component("user")
Service("user")   //Service層
Controller("user")	//web層
@(後臺)Repository("user")	//dao層

//值類型的注入
@Value("tom")
public void setNmae(String name){
...
}

//引用類型的注入
@Autowired  //自定裝配
private Car car;
@Resource(name="car"//手動注入,指定注入哪個名稱的對象
private Car car;

Spring 的 Bean 管理的方式的比較
Alt text

2.2 Sping接入整合Junit測試

RunWith(SpringJUnit4ClassRunner.class)  //幫我們創建容器
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {

    @Resource(name = "user")
    private User u;
    
    @Test
    public void fun1(){
}

2.3 Sping的AOP介紹

2.3.1 底層實現

代理機制

  • Spring的AOP的底層用到兩種代理機制:
  • JDK的動態代理:針對實現了接口的產生代理
  • Cglib的到動態代理:針對沒有實現接口的類產生代理,應用的是底層的字節碼增強的技術,深層當前類的子類對象。

2.3.2 AOP的開發中的相關術語

  • Joinpoint(連接點):所謂連接點是指那些被攔截到的點。在 spring 中,這些點指的是方法,因爲 spring 只 支持方法類型的連接點.
  • Pointcut(切入點):所謂切入點是指我們要對哪些 Joinpoint 進行攔截的定義.
  • Advice(通知/增強):所謂通知是指攔截到 Joinpoint 之後所要做的事情就是通知.通知分爲前置通知,後置 通知,異常通知,最終通知,環繞通知(切面要完成的功能)
  • Introduction(引介):引介是一種特殊的通知在不修改類代碼的前提下, Introduction 可以在運行期爲類 動態地添加一些方法或 Field.
  • Target(目標對象):代理的目標對象
  • Weaving(織入):是指把增強應用到目標對象來創建新的代理對象的過程. spring 採用動態代理織入,而 AspectJ 採用編譯期織入和類裝在期織入
  • Proxy(代理):一個類被 AOP 織入增強後,就產生一個結果代理類
  • Aspect(切面): 是切入點和通知(引介)的結合

2.3.2 AOP的開發

jar包介紹
Alt text
步驟

<!--準備工作:導入aop(約束)命名空間-->

    <!--1.配置目標對象-->
    <!--2.配置通知對象-->
    <!--3.配置將通知織入目標對象-->
    <!-- 配置切入點
        * cn.itcast.service..*ServiceImpl.*(..)
        這個service包下面的任意子包中以ServiceImpl結尾的任意類中的任意方法(任意參數)  可以返回任意類型數據
    -->
前置通知 :在目標方法執行之前執行. 
後置通知 :在目標方法執行之後執行 
環繞通知 :在目標方法執行前和執行後執行 
異常拋出通知:在目標方法執行出現 異常的時候 執行 
最終通知 :無論目標方法是否出現異常 最終通知都會 執行. 

目標類的創建:

//創建接口和類:
 public interface OrderDao {  
 public void save();  
 public void update();  
 public void delete(); 
 public void find(); 
 } 
 public class OrderDaoImpl implements OrderDao { 
 
 @Override  public void save() { 
  System.out.println("保存訂單...");  
@Override  public void update() { 
  System.out.println("修改訂單...");  } 
 
 @Override  public void delete() { 
  System.out.println("刪除訂單...");  } 
 
 @Override  public void find() { 
  System.out.println("查詢訂單...");  } 
 
} 
} 

目標類的配置

<!-- 目標類================ -->  
<bean id="orderDao" class="cn.itcast.spring.demo3.OrderDaoImpl">    </bean>

整合Jubit單元測試

引入 spring-test.jar 
 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:applicationContext.xml") 
public class SpringDemo3 {  
	@Resource(name="orderDao")  
	private OrderDao orderDao;    
	@Test  
	public void demo1(){   
		orderDao.save();   
		orderDao.update();   
		orderDao.delete();   
		orderDao.find();  
} } 

編寫切入面

public class MyAspectXml { 
 // 前置增強  
 public void before(){ 
  System.out.println("前置增強===========");  
  
  } }

配置完成增強

 <!-- 配置切面類 -->  
 <bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>   
 <!-- 進行 aop 的配置 -->  
 <aop:config> 
  <!-- 配置切入點表達式:哪些類的哪些方法需要進行增強 -->   
  <aop:pointcut expression="execution(* cn.itcast.spring.demo3.OrderDao.save(..))" id="pointcut1"/> 
  <!-- 配置切面 -->   
  <aop:aspect ref="myAspectXml">    
  <aop:before method="before" pointcut-ref="pointcut1"/>   
  </aop:aspect>  
  </aop:config> 

切入點表達式:

execution(表達式) 
表達式: [方法訪問修飾符] 方法返回值 包名.類名.方法名(方法的參數)
 public * cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.*.*(..)
* cn.itcast.spring.dao.UserDao+.*(..)
* cn.itcast.spring.dao..*.*(..)

3. Spring整合JDBC

3.1 Spring連接JDBC

導入jar包

Alt text

編寫Dao文件

public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
//引入了JDBCDaoSupport根據連接池創建JDBC模板,直接從父類方法中獲得就可以了

    @Override
    public void save(User u) {
        String sql = "insert into s_user values(null, ?)";
        getJdbcTemplate().update(sql, u.getName());
    }

    @Override
    public void delete(Integer id) {
        String sql = "delete from s_user where id =?";
        getJdbcTemplate().update(sql, id);
    }

    @Override
    public void update(User u) {
        String sql = "update s_user set name = ? where id = ?";
        getJdbcTemplate().update(sql, u.getName(), u.getId());
    }

//查詢單個對象
    @Override
    public User getById(Integer id) {
        String sql = "select * from s_user where id = ?";

        return getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                User u = new User();
                u.setId(rs.getInt("id"));
                u.setName(rs.getString("name"));
                return u;
            }
        });
    }

//查詢值類型
    @Override
    public int getTotalCount() {
        String sql = "select count(*) from t_user  ";
        Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class);
        return count;
    }

//查詢list集合類型
    @Override
    public List<User> getAll() {
        String sql = "select * from s_user";
        List<User> list = getJdbcTemplate().query(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                User u = new User();
                u.setId(rs.getInt("id"));
                u.setName(rs.getString("name"));
                return u;
            }
        });
        return list;
    }

}

Spring配置

<!--指定spring讀取db.properties配置-->
    <context:property-placeholder location="classpath:db.properties"/>
  <!--指定spring讀取db.properties配置-->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
 <!--將JDBCTemplate放入spring容器-->
    <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
     </bean>

    <!-- 3.將UserDao放入spring容器 -->
    <bean name="userDao" class="cn.raine.jsbctemplate.UserDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
     </bean>

3.2 事務

3.2.1 事務特性

  • 原子性 :強調事務的不可分割.
  • 一致性 :事務的執行的前後數據的完整性保持一致.
  • 隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾
  • 持久性 :事務一旦結束,數據就持久到數據庫

3.2.2設置事務隔離級別

  • 未提交讀 :髒讀,不可重複讀,虛讀都有可能發生
  • 已提交讀 :避免髒讀。但是不可重複讀和虛讀有可能發生
  • 可重複讀 :避免髒讀和不可重複讀.但是虛讀有可能發生.
  • 串行化的 :避免以上所有讀問題.
    ####3.2.3 真正管理事務的對象
***** 真正管理事務的對象 
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring JDBC 或 iBatis 進行持久化數據時使用 
org.springframework.orm.hibernate3.HibernateTransactionManager  使用 Hibernate 版本進行持久化數據時使用 

3.2.4 事務的傳播行爲

PROPAGION_XXX :事務的傳播行爲

  • 保證同一個事務中
    PROPAGATION_REQUIRED 支持當前事務,如果不存在 就新建一個(默認) PROPAGATION_SUPPORTS 支持當前事務,如果不存在,就不使用事務
    PROPAGATION_MANDATORY 支持當前事務,如果不存在,拋出異常

  • 保證沒有在同一個事務中
    PROPAGATION_REQUIRES_NEW 如果有事務存在,掛起當前事務,創建一個新的事務
    PROPAGATION_NOT_SUPPORTED 以非事務方式運行,如果有事務存在,掛起當前事務
    PROPAGATION_NEVER 以非事務方式運行,如果有事務存在,拋出異常
    PROPAGATION_NESTED 如果當前事務存在,則嵌套事務執行

3.2.5 Spring管理事務方式

3.2.5.1 xml配置

xml配置

 <!--事務核心管理器,封裝了所欲事務操作,依賴於連接池-->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--事務模板對象-->
    <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

    <!--配置事務通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 以方法爲單位,指定方法應用什麼事務屬性
			isolation:隔離級別
			propagation:傳播行爲
			read-only:是否只讀-->
            <tx:method name="save" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
            <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        </tx:attributes>
    </tx:advice>

    <!--配置織入-->
    <aop:config>
        <!--配置切點表達式-->
        <aop:pointcut id="txPc" expression="execution(* cn.raine.service.*ServiceImpl.*(..))" />
        <!-- 配置切面 : 通知+切點
		 	advice-ref:通知的名稱
		 	pointcut-ref:切點的名稱
	 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
    </aop:config>

 <bean name="accountDao" class="cn.raine.dao.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <bean name="accountService" class="cn.raine.service.AccountServiceImpl">
        <property name="ad" ref="accountDao"></property>
        <property name="tt" ref="transactionTemplate"></property>
    </bean>

在Service中調用模板

    public void transfer(Integer from, Integer to, Double money) {
        tt.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                //減錢
                ad.decreaseMoney(from, money);

                //加錢
                ad.increaseMoney(to, money);
            }
        });
3.2.5.2 註解配置

開啓註解管理事務

  <!--開啓使用註解管理aop事務-->
    <tx:annotation-driven/>

使用註解

   @Override
    @Transactional(isolation = ![這裏寫圖片描述](http://img.blog.csdn.net/20171210101028916?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTGVicm9uX3hpYQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW, readOnly = false)
    public void transfer(Integer from, Integer to, Double money) {
        //減錢
        ad.decreaseMoney(from, money);
      //  int i = 1/0;
        //加錢
        ad.increaseMoney(to, money);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章