溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring[02.基礎(chǔ)知識整理(下)]

發(fā)布時間:2020-08-09 23:28:40 來源:網(wǎng)絡(luò) 閱讀:978 作者:IMUKL8 欄目:軟件技術(shù)

Bean使用外部屬性文件

  • 在配置文件里配置 Bean 時, 有時需要在 Bean 的配置里混入系統(tǒng)部署的細(xì)節(jié)信息(例如: 文件路徑, 數(shù)據(jù)源配置信息等). 而這些部署細(xì)節(jié)實際上需要和 Bean 配置相分離

  • Spring 提供了一個 PropertyPlaceholderConfigurer 的 BeanFactory 后置處理器, 這個處理器允許用戶將 Bean 配置的部分內(nèi)容外移到屬性文件中. 可以在 Bean 配置文件里使用形式為 ${var} 的變量, PropertyPlaceholderConfigurer 從屬性文件里加載屬性, 并使用這些屬性來替換變量.

  • xml context加載外部配置文件<context:property-placeholder location="">

Spel表達(dá)式

是一個支持運行時查詢和操作對象圖的強大的表達(dá)式語言

通過 SpEL 可以實現(xiàn):

  • 通過 bean 的 id 對 bean 進(jìn)行引用
  • 調(diào)用方法以及引用對象中的屬性
  • 計算表達(dá)式的值
  • 正則表達(dá)式的匹配

案例

驗證郵箱

^[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)"+"*@[A-Za-z0-9]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$

Bean的生命周期

生命周期

  • Spring IOC 容器可以管理 Bean 的生命周期, Spring 允許在 Bean 生命周期的特定點執(zhí)行定制的任務(wù).
  • Spring IOC 容器對 Bean 的生命周期進(jìn)行管理的過程:
    • 通過構(gòu)造器或工廠方法創(chuàng)建 Bean 實例
    • 為 Bean 的屬性設(shè)置值和對其他 Bean 的引用
    • 調(diào)用 Bean 的初始化方法
    • Bean 可以使用了
    • 當(dāng)容器關(guān)閉時, 調(diào)用 Bean 的銷毀方法
  • 在 Bean 的聲明里設(shè)置 init-method 和 destroy-method 屬性, 為 Bean 指定初始化和銷毀方法.

Bean后置處理器

基本介紹
  • Bean 后置處理器允許在調(diào)用初始化方法前后對 Bean 進(jìn)行額外的處理.
  • Bean 后置處理器對 IOC 容器里的所有 Bean 實例逐一處理, 而非單一實例. 其典型應(yīng)用是: 檢查 Bean 屬性的正確性或根據(jù)特定的標(biāo)準(zhǔn)更改 Bean 的屬性.
  • 對Bean 后置處理器而言, 需要實現(xiàn)BeanPostProcessor接口.

在初始化方法被調(diào)用前后, Spring 將把每個 Bean 實例分別傳遞給上述接口的以下兩個方法:

public class MyBeanPostProcesser implements BeanPostProcessor {

    // 在init-method之前調(diào)用
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessBeforeInitialization:  " + s);
        return o;
    }

    // 在init-method之后調(diào)用
    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("postProcessAfterInitialization:  " + s);
        return o;
    }
}
后置處理器特性

//Bean 后置處理器允許在調(diào)用初始化方法前后對 Bean 進(jìn)行額外的處理.
//Bean 后置處理器對 IOC 容器里的所有 Bean 實例逐一處理, 而非單一實例.
// 其典型應(yīng)用是: 檢查 Bean 屬性的正確性或根據(jù)特定的標(biāo)準(zhǔn)更改 Bean 的屬性.

//采用前置和后置處理之后
//首先運行構(gòu)造函數(shù)
//然后給屬性賦值
//然后訪問前置處理函數(shù)
//然后訪問init函數(shù)
//然后訪問后置處理函數(shù)
//然后輸出結(jié)果
//最后訪問destroy函數(shù)

@Autowired 自動裝配 Bean

  • 構(gòu)造器, 普通字段(即使是非 public), 一切具有參數(shù)的方法都可以應(yīng)用@Authwired 注解
    默認(rèn)情況下, 所有使用 @Authwired 注解的屬性都需要被設(shè)置. 當(dāng) Spring 找不到匹配的 Bean 裝配屬性時, 會拋出異常, 若某一屬性允許不被設(shè)置, 可以設(shè)置 @Authwired 注解的 required 屬性為 false

  • 默認(rèn)情況下, 當(dāng) IOC 容器里存在多個類型兼容的 Bean 時, 通過類型的自動裝配將無法工作. 此時可以在 @Qualifier 注解里提供 Bean 的名稱. Spring 允許對方法的入?yún)?biāo)注 @Qualifiter 已指定注入 Bean 的名稱

  • @Authwired 注解也可以應(yīng)用在數(shù)組類型的屬性上, 此時 Spring 將會把所有匹配的 Bean 進(jìn)行自動裝配.

  • @Authwired 注解也可以應(yīng)用在集合屬性上, 此時 Spring 讀取該集合的類型信息, 然后自動裝配所有與之兼容的 Bean.

  • @Authwired 注解用在 java.util.Map 上時, 若該 Map 的鍵值為 String, 那么 Spring 將自動裝配與之 Map 值類型兼容的 Bean, 此時 Bean 的名稱作為鍵值

AOP與AspectJ

概述

是一種新的方法論, 是對傳統(tǒng) OOP(Object-Oriented Programming, 面向?qū)ο缶幊? 的補充.

AOP 的主要編程對象是切面(aspect), 而切面模塊化橫切關(guān)注點.

在應(yīng)用 AOP 編程時, 仍然需要定義公共功能, 但可以明確的定義這個功能在哪里, 以什么方式應(yīng)用, 并且不必修改受影響的類. 這樣一來橫切關(guān)注點就被模塊化到特殊的對象(切面)里.

AOP 的好處:

  • 每個事物邏輯位于一個位置, 代碼不分散, 便于維護和升級
  • 業(yè)務(wù)模塊更簡潔, 只包含核心業(yè)務(wù)代碼.

術(shù)語

  • 切面(Aspect): 橫切關(guān)注點(跨越應(yīng)用程序多個模塊的功能)被模塊化的特殊對象
  • 通知(Advice): 切面必須要完成的工作
  • 目標(biāo)(Target): 被通知的對象
  • 代理(Proxy): 向目標(biāo)對象應(yīng)用通知之后創(chuàng)建的對象
  • 連接點(Joinpoint):程序執(zhí)行的某個特定位置:如類某個方法調(diào)用前、調(diào)用后、方法拋出異常后等。連接點由兩個信息確定:方法表示的程序執(zhí)行點;相對點表示的方位。例如 ArithmethicCalculator#add() 方法執(zhí)行前的連接點,執(zhí)行點為 ArithmethicCalculator#add(); 方位為該方法執(zhí)行前的位置
  • 切點(pointcut):每個類都擁有多個連接點:例如 ArithmethicCalculator 的所有方法實際上都是連接點,即連接點是程序類中客觀存在的事務(wù)。AOP 通過切點定位到特定的連接點。類比:連接點相當(dāng)于數(shù)據(jù)庫中的記錄,切點相當(dāng)于查詢條件。切點和連接點不是一對一的關(guān)系,一個切點匹配多個連接點,切點通過 org.springframework.aop.Pointcut 接口進(jìn)行描述,它使用類和方法作為連接點的查詢條件。

AspectJ

AspectJ:Java 社區(qū)里最完整最流行的 AOP 框架.在 Spring2.0 以上版本中, 可以使用基于 AspectJ 注解或基于 XML 配置的 AOP

依賴包:

  • aopalliance-1.0.jar
  • aspectjrt.jar
  • aspectjtools.jar
  • aspectjweaver.jar
  • org.aspectj.matcher.jar

AspectJ通知注解

  • @Before: 前置通知, 在方法執(zhí)行之前執(zhí)行
  • @After: 后置通知, 在方法執(zhí)行之后執(zhí)行
  • @AfterRunning: 返回通知, 在方法返回結(jié)果之后執(zhí)行
  • @AfterThrowing: 異常通知, 在方法拋出異常之后
  • @Around: 環(huán)繞通知, 圍繞著方法執(zhí)行

    切入點合并

  • @Pointcut 將多個被限制的bean或者bean方法合并為一個集合,AspectJ通知注解可以直接調(diào)用合并切入點的方法,
    如: combinePointCut

    Order

  • 制定切面的優(yōu)先級
  • 數(shù)字越小,代表優(yōu)先級越高

案例

@Aspect
@Order(0)
public class AspectProcessor {

    // 合并切入點
    @Pointcut("execution(* com.demo.aop.aspect.CalculatorImpl.*(..)))")
    public void combinePointCut(){}

    // 此函數(shù)在指定的bean方法執(zhí)行前響應(yīng)
    // @Before("execution (* com.demo.aop.aspect.CalculatorImpl.*(..))")
    @Before("combinePointCut()")
    public void beforeAspectProcessor(JoinPoint joinPoint){
        System.out.println("beforeAspectProcessor method name: " + joinPoint.getSignature().getName());
        System.out.println("beforeAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs()));
    }

    // 此函數(shù)在指定的bean方法執(zhí)行后響應(yīng)
    // @After("execution (* com.demo.aop.aspect.CalculatorImpl.*(..))")
    @After("combinePointCut()")
    public void afterAspectProcessor(JoinPoint joinPoint){
        System.out.println("afterAspectProcessor method name: " + joinPoint.getSignature().getName());
        System.out.println("afterAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs()));
    }

//    此函數(shù)在指定的bean方法執(zhí)行前、后響應(yīng)
//    @Around("combinePointCut()")
//    public void around(ProceedingJoinPoint pjp) throws Throwable{
//        System.out.println("已經(jīng)記錄下操作日志@Around 方法執(zhí)行前");
//        pjp.proceed();
//        System.out.println("已經(jīng)記錄下操作日志@Around 方法執(zhí)行后");
//    }

    // 如果只想在連接點返回的時候記錄, 應(yīng)使用返回通知代替后置通知
    @AfterReturning(value = "combinePointCut()", returning = "result")
    public void afterReturningAspectProcessor(JoinPoint joinPoint, Object result){
        System.out.println("afterReturningAspectProcessor method name: " + joinPoint.getSignature().getName());
        System.out.println("afterReturningAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs()));
        System.out.println("afterReturningAspectProcessor method result: " + result);

    }

    // 異常通知
    @AfterThrowing(value = "combinePointCut()", throwing = "e")
    public void afterThrowingAspectProcessor(JoinPoint joinPoint, Exception e){
        System.out.println("afterThrowingAspectProcessor method name: " + joinPoint.getSignature().getName());
        System.out.println("afterThrowingAspectProcessor method args: " + Arrays.asList(joinPoint.getArgs()));
        System.out.println("afterThrowingAspectProcessor method throwing: " + e);
    }
}
  • 將 aop Schema 添加到 <beans> 根元素中.
  • 要在 Spring IOC 容器中啟用 AspectJ 注解支持, 只要在 Bean 配置文件中定義一個空的 XML 元素 <aop:aspectj-autoproxy>
  • 當(dāng) Spring IOC 容器偵測到 Bean 配置文件中的 <aop:aspectj-autoproxy> 元素時, 會自動為與 AspectJ 切面匹配的 Bean 創(chuàng)建代理

<!--讓aspectj @before @after注解生效-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<context:component-scan base-package="com.demo.aop.aspect"></context:component-scan>

通過代理方式實現(xiàn)AspectJ

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * Created by plusplusxu on 2017/10/23.
 *
 * 動態(tài)代理模式主要用來做方法的增強,讓你可以在不修改源碼的情況下,增強一些方法,
 * 在方法執(zhí)行前后做任何你想做的事情(甚至根本不去執(zhí)行這個方法),
 * 因為在InvocationHandler的invoke方法中,你可以直接獲取正在調(diào)用方法對應(yīng)的Method對象,
 * 具體應(yīng)用的話,比如可以添加調(diào)用日志,做事務(wù)控制等。
 * 動態(tài)代理是設(shè)計模式當(dāng)中代理模式的一種。
 */
@Repository
public class CalculatorImplProxy {

    @Autowired
    private Calculator target;

    public Calculator getProxy(){
        Calculator proxy = null;

        // 代理對象由哪一個加載器加載
        ClassLoader loader = target.getClass().getClassLoader();

        // 代理對象的內(nèi)容
        Class[] interfaces = new Class[]{Calculator.class};

        // 當(dāng)調(diào)用代理對象的方法的時候,該方法被執(zhí)行
        InvocationHandler h = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                // 代理對象方法執(zhí)行前操作
                System.out.println("method: " + method.getName() + "  " + "  args:  " + Arrays.asList(args));

                Object result = method.invoke(target, args);

                // 代理對象方法執(zhí)行后操作
                System.out.println("method: " + method.getName() + "  " + "  args:  " + Arrays.asList(args) + "  result: " + result);

                return result;
            }
        };

        proxy = (Calculator)Proxy.newProxyInstance(loader, interfaces, h);

        return proxy;
    }
}

JDBC

JdbcTemplate

作為 Spring JDBC 框架的核心, JDBC 模板的設(shè)計目的是為不同類型的 JDBC 操作提供模板方法. 每個模板方法都能控制整個過程, 并允許覆蓋過程中的特定任務(wù). 通過這種方式, 可以在盡可能保留靈活性的情況下, 將數(shù)據(jù)庫存取的工作量降到最低.

  • 每次使用都創(chuàng)建一個 JdbcTemplate 的新實例, 這種做法效率很低下.
  • JdbcTemplate 類被設(shè)計成為線程安全的, 所以可以再 IOC 容器中聲明它的單個實例, 并將這個實例注入到所有的 DAO 實例中.
  • JdbcTemplate 也利用了 Java 1.5 的特定(自動裝箱, 泛型, 可變長度等)來簡化開發(fā)

JdbcDaoSupport

該類聲明了 jdbcTemplate 屬性, 它可以從 IOC 容器中注入, 或者自動從數(shù)據(jù)源中創(chuàng)建.

package com.mysql;

import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by plusplusxu on 2017/10/25.
 *
 * 操作mysql的數(shù)據(jù)類
 *
 * JdbcTemplate 類被設(shè)計成為線程安全的, 所以可以再 IOC 容器中聲明它的單個實例, 并將這個實例注入到所有的 DAO 實例中.
 */
public class ProjectDao {

    public ProjectDao(JdbcTemplate jdbcTemplateObject) {
        this.jdbcTemplateObject = jdbcTemplateObject;
    }

    public ProjectDao() {
    }

    public JdbcTemplate getJdbcTemplateObject() {
        return jdbcTemplateObject;
    }

    public void setJdbcTemplateObject(JdbcTemplate jdbcTemplateObject) {
        this.jdbcTemplateObject = jdbcTemplateObject;
    }

    // spring 提供的訪問數(shù)據(jù)庫的工具類,需要配置javax.sql.DataSource
    // 本例中在applicationContext中配置的mysql數(shù)據(jù)源
    private JdbcTemplate jdbcTemplateObject;

    // 添加一條項目記錄
    // tbl_devops_project為vsdo數(shù)據(jù)庫的項目表(Project)
    public void addproject(Project project) {
        String sql = "INSERT INTO tbl_devops_project(name,public,language,description," +
                "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " +
                "VALUES(?,?,?,?,?,?,?,?,?,?)";

        try {
            jdbcTemplateObject.update(sql, project.getName(),project.getPub(),project.getLanguage(),project.getDescription(),
                    project.getAdmin(),project.getMembers(),project.getGitlab_id(),
                    project.getGitlab_url(),project.getCode_styles(),project.getSonar_lint_server_url());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 根據(jù)項目名刪除記錄
    public void delprojectbyname(String name) {
        String sql = "DELETE FROM tbl_devops_project WHERE name=?";

        try {
            jdbcTemplateObject.update(sql,name);
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 刪除所有項目
    public void delallproject() {
        String sql = "DELETE FROM tbl_devops_project";
        try {
            jdbcTemplateObject.update(sql);
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 更新某個項目
    public void updproject(Project project) {
        String sql = "UPDATE tbl_devops_project set description=? WHERE name=?";
        try {
            jdbcTemplateObject.update(sql,project.getDescription(), project.getName());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 獲取所有項目
    public List<Project> allproject() {
        List<Project> projects = null;
        String sql = "SELECT * FROM tbl_devops_project";
        try {
            // ProjectMapper 項目表的映射類
            projects = jdbcTemplateObject.query(sql, new ProjectMapper());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return projects;
    }

    // 查詢項目名對應(yīng)的記錄
    public List<Project> queryprojectbyname(String name) {
        List<Project> projects = null;
        String sql = "SELECT * FROM tbl_devops_project WHERE name=?";
        try {
            projects = jdbcTemplateObject.query(sql, new Object[]{name}, new ProjectMapper());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return projects;
    }

    // 打印所有項目
    public void displayall(){
        List<Project> projects = allproject();
        for(Project s : projects){
            System.out.println(s);
        }
    }

    // 批量插入
    public void insertBatch(final List<Project> projects){
        String sql = "INSERT INTO tbl_devops_project(name,public,language,description," +
                "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " +
                "VALUES(?,?,?,?,?,?,?,?,?,?)";

        jdbcTemplateObject.batchUpdate(sql, new BatchPreparedStatementSetter() {

            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Project project = projects.get(i);

                ps.setString(1, project.getName());
                ps.setBoolean(2, project.getPub());
                ps.setString(3, project.getLanguage());
                ps.setString(4, project.getDescription());
                ps.setString(5, project.getAdmin());
                ps.setString(6, project.getMembers());
                ps.setInt(7, project.getGitlab_id());
                ps.setString(8, project.getGitlab_url());
                ps.setString(9, project.getCode_styles());
                ps.setString(10, project.getSonar_lint_server_url());
            }

            @Override
            public int getBatchSize() {
                return projects.size();
            }
        });
    }
}
package com.mysql;

import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by plusplusxu on 2017/10/26.
 *
 * 繼承于JdbcDaoSupport,直接封裝了JdbcTemplate,寫起來更方便
 *
 * 該類聲明了 jdbcTemplate 屬性, 它可以從 IOC 容器中注入, 或者自動從數(shù)據(jù)源中創(chuàng)建.
 *
 */
public class JdbcDaoSupportImpl extends JdbcDaoSupport {
    // 添加一條項目記錄
    // tbl_devops_project為vsdo數(shù)據(jù)庫的項目表(Project)
    public void addproject(Project project) {
        String sql = "INSERT INTO tbl_devops_project(name,public,language,description," +
                "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " +
                "VALUES(?,?,?,?,?,?,?,?,?,?)";

        try {
            this.getJdbcTemplate().update(sql, project.getName(),project.getPub(),project.getLanguage(),project.getDescription(),
                    project.getAdmin(),project.getMembers(),project.getGitlab_id(),
                    project.getGitlab_url(),project.getCode_styles(),project.getSonar_lint_server_url());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 根據(jù)項目名刪除記錄
    public void delprojectbyname(String name) {
        String sql = "DELETE FROM tbl_devops_project WHERE name=?";

        try {
            this.getJdbcTemplate().update(sql,name);
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 刪除所有項目
    public void delallproject() {
        String sql = "DELETE FROM tbl_devops_project";
        try {
            this.getJdbcTemplate().update(sql);
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 更新某個項目
    public void updproject(Project project) {
        String sql = "UPDATE tbl_devops_project set description=? WHERE name=?";
        try {
            this.getJdbcTemplate().update(sql,project.getDescription(), project.getName());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return ;
    }

    // 獲取所有項目
    public List<Project> allproject() {
        List<Project> projects = null;
        String sql = "SELECT * FROM tbl_devops_project";
        try {
            // ProjectMapper 項目表的映射類
            projects = this.getJdbcTemplate().query(sql, new ProjectMapper());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return projects;
    }

    // 查詢項目名對應(yīng)的記錄
    public List<Project> queryprojectbyname(String name) {
        List<Project> projects = null;
        String sql = "SELECT * FROM tbl_devops_project WHERE name=?";
        try {
            projects = this.getJdbcTemplate().query(sql, new Object[]{name}, new ProjectMapper());
        }
        catch (Exception e){
            System.out.println(e);
        }

        return projects;
    }

    // 打印所有項目
    public void displayall(){
        List<Project> projects = allproject();
        for(Project s : projects){
            System.out.println(s);
        }
    }

    // 批量插入
    public void insertBatch(final List<Project> projects){
        String sql = "INSERT INTO tbl_devops_project(name,public,language,description," +
                "admin, members, gitlab_id,gitlab_url,code_styles,sonar_lint_server_url) " +
                "VALUES(?,?,?,?,?,?,?,?,?,?)";

        this.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {

            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Project project = projects.get(i);

                ps.setString(1, project.getName());
                ps.setBoolean(2, project.getPub());
                ps.setString(3, project.getLanguage());
                ps.setString(4, project.getDescription());
                ps.setString(5, project.getAdmin());
                ps.setString(6, project.getMembers());
                ps.setInt(7, project.getGitlab_id());
                ps.setString(8, project.getGitlab_url());
                ps.setString(9, project.getCode_styles());
                ps.setString(10, project.getSonar_lint_server_url());
            }

            @Override
            public int getBatchSize() {
                return projects.size();
            }
        });
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--利用spring原生的DriverManagerDataSource和mysql驅(qū)動配置數(shù)據(jù)源-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <!--注意一下&characterEncoding要修改為&characterEncoding-->
        <!--vsdo為mysql數(shù)據(jù)庫名稱-->
        <property name="url" value="jdbc:mysql://localhost:3306/vsdo?useUnicode=true&characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456" />
    </bean>

    <!---->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--配置數(shù)據(jù)源依賴-->
        <property name="dataSource" ref="datasource" />
    </bean>

    <bean id="projectDaoImp" class="com.mysql.ProjectDao">
        <!--添加jdbc訪問類依賴-->
        <property name="jdbcTemplateObject" ref="jdbcTemplate"></property>
    </bean>

    <bean id="jdbcDaoSupportImpl" class="com.mysql.JdbcDaoSupportImpl">
        <property name="dataSource" ref="datasource"></property>
    </bean>
</beans>

事務(wù)

事務(wù)管理是企業(yè)級應(yīng)用程序開發(fā)中必不可少的技術(shù), 用來確保數(shù)據(jù)的完整性和一致性.

事務(wù)就是一系列的動作, 它們被當(dāng)做一個單獨的工作單元. 這些動作要么全部完成, 要么全部不起作用

事務(wù)的四個關(guān)鍵屬性(ACID)

  • 原子性(atomicity): 事務(wù)是一個原子操作, 由一系列動作組成. 事務(wù)的原子性確保動作要么全部完成要么完全不起作用.
  • 一致性(consistency): 一旦所有事務(wù)動作完成, 事務(wù)就被提交. 數(shù)據(jù)和資源就處于一種滿足業(yè)務(wù)規(guī)則的一致性狀態(tài)中.
  • 隔離性(isolation): 可能有許多事務(wù)會同時處理相同的數(shù)據(jù), 因此每個事物都應(yīng)該與其他事務(wù)隔離開來, 防止數(shù)據(jù)損壞.
  • 持久性(durability): 一旦事務(wù)完成, 無論發(fā)生什么系統(tǒng)錯誤, 它的結(jié)果都不應(yīng)該受到影響. 通常情況下, 事務(wù)的結(jié)果被寫到持久化存儲器中.

Spring 既支持編程式事務(wù)管理, 也支持聲明式的事務(wù)管理.

  • 編程式事務(wù)管理: 將事務(wù)管理代碼嵌入到業(yè)務(wù)方法中來控制事務(wù)的提交和回滾. 在編程式管理事務(wù)時, 必須在每個事務(wù)操作中包含額外的事務(wù)管理代碼.
  • 聲明式事務(wù)管理: 大多數(shù)情況下比編程式事務(wù)管理更好用. 它將事務(wù)管理代碼從業(yè)務(wù)方法中分離出來, 以聲明的方式來實現(xiàn)事務(wù)管理. 事務(wù)管理作為一種橫切關(guān)注點, 可以通過 AOP 方法模塊化. Spring 通過 Spring AOP 框架支持聲明式事務(wù)管理.

用 @Transactional 注解聲明式地管理事務(wù)

Spring 還允許簡單地用 @Transactional 注解來標(biāo)注事務(wù)方法.

  • 為了將方法定義為支持事務(wù)處理的, 可以為方法添加 @Transactional 注解. 根據(jù) Spring AOP 基于代理機制, 只能標(biāo)注公有方法.

  • 可以在方法或者類級別上添加 @Transactional 注解. 當(dāng)把這個注解應(yīng)用到類上時, 這個類中的所有公共方法都會被定義成支持事務(wù)處理的.
  • 在 Bean 配置文件中只需要啟用 <tx:annotation-driven> 元素, 并為之指定事務(wù)管理器就可以了.
  • 如果事務(wù)處理器的名稱是 transactionManager, 就可以在<tx:annotation-driven> 元素中省略 transaction-manager 屬性. 這個元素會自動檢測該名稱的事務(wù)處理器.

Spring[02.基礎(chǔ)知識整理(下)]

事務(wù)的傳播行為

當(dāng)事務(wù)方法被另一個事務(wù)方法調(diào)用時, 必須指定事務(wù)應(yīng)該如何傳播. 例如: 方法可能繼續(xù)在現(xiàn)有事務(wù)中運行, 也可能開啟一個新事務(wù), 并在自己的事務(wù)中運行.

Spring[02.基礎(chǔ)知識整理(下)]

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI