日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring 实践 -拾遗

發布時間:2025/3/17 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring 实践 -拾遗 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Spring 實踐

標簽: Java與設計模式


Junit集成

前面多次用到@RunWith與@ContextConfiguration,在測試類添加這兩個注解,程序就會自動加載Spring配置并初始化Spring容器,方便Junit與Spring集成測試.使用這個功能需要在pom.xml中添加如下依賴:

  • pom.xml
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>4.2.0.RELEASE</version> </dependency>
  • 以@RunWith和@ContextConfiguration加載Spring容器
/*** Spring 整合 Junit* Created by jifang on 15/12/9.*/ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring/applicationContext.xml") public class BeanTest {@Autowiredprivate Bean bean;@Testpublic void testConstruct() {Car car = bean.getCar();System.out.println(car);} }

Web集成

我們可以利用ServletContext容器保存數據的唯一性, 以及ServletContextListener會在容器初始化時只被調用一次的特性. 在web.xml中配置spring-web包下的ContextLoaderListener來加載Spring配置文件/初始化Spring容器:

  • pom.xml/spring-web
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>4.2.0.RELEASE</version> </dependency>
  • 配置監聽器(web.xml)
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
  • 加載Spring配置文件
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/applicationContext.xml</param-value> </context-param>

附: 完整web.xml文件git地址.

  • 測試Servlet
@WebServlet(urlPatterns = "/servlet") public class Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());Bean bean = context.getBean("bean", Bean.class);Car car = bean.getCar();System.out.println(car);} }

在應用中,普通的JavaBean由Spring管理,可以使用@Autowired自動注入.但Filter與Servlet例外,他們都是由Servlet容器管理,因此其屬性不能用Spring注入,所以在實際項目中,一般都不會直接使用Servlet,而是用SpringMVC/WebX/Struts2之類的MVC框架以簡化開發,后面會有專門的博客介紹這類框架,在此就不做深入介紹了.

  • 注: 運行Servlet不要忘記添加servlet-api依賴:
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version> </dependency>

文件加載

1. 引入properties

可以將需要經常修改的屬性參數值放到properties文件, 并在Spring文件中引入.

  • db.properties
## Data Source mysql.driver.class=com.mysql.jdbc.Driver mysql.url=jdbc:mysql://host:port/db?useUnicode=true&characterEncoding=UTF8 mysql.user=user mysql.password=password

注意: value后不能有空格.

1.1 property-placeholde引入

在Spring配置文件中使用<context:property-placeholder/>標簽引入properties文件,XML文件可通過${key}引用, Java可通過@Value("${key}")引用:

  • XML
<context:property-placeholder location="classpath:common.properties"/><bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig"><property name="driverClassName" value="${mysql.driver.class}"/><property name="jdbcUrl" value="${mysql.url}"/><property name="username" value="${mysql.user}"/><property name="password" value="${mysql.password}"/> </bean>
  • Java
@Component public class AccessLog {@Value("${mysql.url}")private String value;// ... }

1.2 PropertiesFactoryBean引入

Spring提供了org.springframework.beans.factory.config.PropertiesFactoryBean,以加載properties文件, 方便在JavaBean中注入properties屬性值.

  • XML
<bean id="commonProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"><property name="locations"><list><value>classpath*:common.properties</value></list></property> </bean>
  • Java
@Controller public class Bean {@Value("#{commonProperties['bean.properties.name']}")private String name;// ... }

2. import其他Spring配置

如果Spring的配置項過多,可以按模塊將配置劃分多個配置文件(-datasource.xml/-dubbo-provider.xml/-bean.xml), 并由主配置applicationContext.xml文件引用他們,此時可用<import/>標簽引入:

<import resource="applicationContext-bean.xml"/> <import resource="applicationContext-dubbo-provider.xml"/> <import resource="applicationContext-dubbo-consumer.xml"/>

事務管理

Spring事務管理高層抽象主要由PlatformTransactionManager/TransactionDefinition/TransactionStatus三個接口提供支持:


PlatformTransactionManager(事務管理器)

PlatformTransactionManager的主要功能是事務管理,Spring為不同的持久層框架提供了不同的PlatformTransactionManager實現:

事務描述
DataSourceTransactionManagerJDBCTemplate/MyBatis/iBatis持久化使用
HibernateTransactionManagerHibernate持久化使用
JpaTransactionManagerJPA持久化使用
JdoTransactionManagerJDO持久化使用
JtaTransactionManagerJTA實現管理事務,一個事務跨越多個資源時使用

因此使用Spring管理事務,需要為不同持久層配置不同事務管理器實現.


TransactionDefinition(事務定義信息)

TransactionDefinition提供了對事務的相關配置, 如事務隔離級別/傳播行為/只讀/超時等:

  • 隔離級別(isolation)
    為解決事務并發引起的問題(臟讀/幻讀/不可重復讀),引入四個隔離級別:
隔離級別描述
DEFAULT使用數據庫默認的隔離級別
READ_UNCOMMITED讀未提交
READ_COMMITTED讀已提交(Oracle默認)
REPEATABLE_READ可重復讀(MySQL默認)
SERIALIZABLE串行化

關于事務隔離級別的討論, 可參考我的博客JDBC基礎-事務隔離級別部分.

  • 傳播行為(propagation)
    傳播行為不是數據庫的特性, 而是為了在業務層解決兩個事務相互調用的問題:
傳播類型描述
REQUIRED支持當前事務,如果不存在就新建一個(默認)
SUPPORTS支持當前事務,如果不存在就不使用事務
MANDATORY支持當前事務,如果不存在則拋出異常
REQUIRES_NEW如果有事務存在,則掛起當前事務新建一個
NOT_SUPPORTED以非事務方式運行,如果有事務存在則掛起當前事務
NEVER以非事務方式運行,如果有事務存在則拋出異常
NESTED如果當前事務存在,則嵌套事務執行(只對DataSourceTransactionManager有效)
  • 超時時間(timeout)
  • 只讀(read-only)
    只讀事務, 不能執行INSERT/UPDATE/DELETE操作.

TransactionStatus(事務狀態信息)

獲得事務執行過程中某一個時間點狀態.


聲明式事務管理

Spring聲明式事務管理:無需要修改原來代碼,只需要為Spring添加配置(XML/Annotation),就可以為目標代碼添加事務管理功能.

需求: 轉賬案例(使用MyBatis).

  • AccountDAO
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.fq.dao.AccountDAO"><update id="transferIn">UPDATE accountSET money = money + #{0}WHERE name = #{1};</update><update id="transferOut">UPDATE accountSET money = money - #{0}WHERE name = #{1};</update> </mapper> /*** @author jifang* @since 16/3/3 上午11:16.*/ public interface AccountDAO {void transferIn(Double inMoney, String name);void transferOut(Double outMoney, String name); }
  • Service
public interface AccountService {void transfer(String from, String to, Double money); } @Service("service") public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDAO dao;@Overridepublic void transfer(String from, String to, Double money) {dao.transferOut(money, from);// 此處拋出異常, 沒有事務將導致數據不一致int a = 1 / 0;dao.transferIn(money, to);} }
  • mybatis-configuration.xml/applicationContext-datasource.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><!-- 加載mapper映射文件 --><mappers><mapper resource="mybatis/mapper/AccountDAO.xml"/></mappers> </configuration> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:db.properties"/><!-- 配置數據源 --><bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig"><property name="driverClassName" value="${mysql.driver.class}"/><property name="jdbcUrl" value="${mysql.url}"/><property name="username" value="${mysql.user}"/><property name="password" value="${mysql.password}"/><property name="maximumPoolSize" value="5"/><property name="maxLifetime" value="700000"/><property name="idleTimeout" value="600000"/><property name="connectionTimeout" value="10000"/><property name="dataSourceProperties"><props><prop key="dataSourceClassName">com.mysql.jdbc.jdbc2.optional.MysqlDataSource</prop><prop key="cachePrepStmts">true</prop><prop key="prepStmtCacheSize">250</prop><prop key="prepStmtCacheSqlLimit">2048</prop></props></property></bean><bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"><constructor-arg ref="hikariConfig"/></bean><!-- 配置SqlSessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:mybatis/mybatis-configuration.xml"/></bean><!-- 基于包掃描的mapper配置 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.fq.dao"/><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/></bean></beans>
  • 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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.fq.service"/><import resource="applicationContext-datasource.xml"/> </beans>
  • Client
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring/applicationContext.xml") public class SpringClient {@Autowiredprivate AccountService service;@Testpublic void client() {service.transfer("from", "to", 10D);} }

執行以上代碼, 將會導致數據前后不一致.


XML配置

Spring事務管理依賴AOP,而AOP需要定義切面(Advice+PointCut),在Spring內部提供了事務管理的默認Adviceorg.springframework.transaction.interceptor.TransactionInterceptor,并且Spring為了簡化事務配置,引入tx標簽:

  • 引入tx的命名空間,配置Advice:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/> </bean><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 事務配置屬性, 對什么方法應用怎樣的配置, 成為TransactionDefinition對象 --><tx:attributes><!--name: 方法名, 支持通配符isolation: 隔離級別propagation: 傳播行為timeout: 超時時間read-only: 是否只讀rollback-for: 配置異常類型, 發生這些異常回滾事務no-rollback-for: 配置異常類型, 發生這些異常不回滾事務--><tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false"/></tx:attributes> </tx:advice>
  • 配置切面
    Spring事務管理Advice基于SpringAOP,因此使用<aop:advisor/>配置:
<aop:config><aop:advisor advice-ref="txAdvice" pointcut="execution(* com.fq.service.impl.AccountServiceImpl.*(..))"/> </aop:config>

注解配置

使用注解配置事務, 可以省略切點的定義(因為注解放置位置就已經確定了PointCut的置), 只需配置Advice即可:

  • 激活注解事務管理功能
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/> </bean><tx:annotation-driven transaction-manager="transactionManager"/>
  • 在需要管理事務的業務類/業務方法上添加@Transactional注解
@Override @Transactional(transactionManager = "transactionManger", readOnly = true) public void transfer(String from, String to, Double money) {// ... }

可以在注解@Transactional中配置與XML相同的事務屬性(isolation/propagation等).


實踐

更推薦使用XML方式來配置事務,實際開發時一般將事務集中配置管理. 另外, 事務的isolation/propagation一般默認的策略就已經足夠, 反而我們需要配置是否只讀(比如MySQL主從備份時,主庫一般提供讀寫操作,而從庫只提供讀操作), 因此其配置可以如下:

<!-- 配置聲明式事務 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/> </bean><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 定義方法的過濾規則 --><tx:attributes><!-- 定義所有get開頭的方法都是只讀的 --><tx:method name="get*" read-only="true"/><tx:method name="find*" read-only="true"/><tx:method name="select*" read-only="true"/><tx:method name="*"/></tx:attributes> </tx:advice><!-- 配置事務AOP --> <aop:config><!-- 定義切點 --><aop:pointcut id="dao" expression="execution (* com.fq.core.dao.*.*(..))"/><!-- 為切點定義通知 --><aop:advisor advice-ref="txAdvice" pointcut-ref="dao"/> </aop:config>
  • 主從
<tx:advice id="txAdvice_slave" transaction-manager="transactionManager_slave"><!-- 定義方法的過濾規則 --><tx:attributes><tx:method name="*" read-only="true"/></tx:attributes> </tx:advice><tx:advice id="txAdvice_master" transaction-manager="transactionManager_slave"><!-- 定義方法的過濾規則 --><tx:attributes><!-- 定義所有get開頭的方法都是只讀的 --><tx:method name="get*" read-only="true"/><tx:method name="find*" read-only="true"/><tx:method name="select*" read-only="true"/><tx:method name="*"/></tx:attributes> </tx:advice>

總結

以上是生活随笔為你收集整理的Spring 实践 -拾遗的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 免费h片网站 | 免费看特级毛片 | 久久精品综合网 | 国产精品91一区 | 欧美偷拍一区二区 | 国产又大又黑又粗 | 男插女青青影院 | 天天综合天天干 | 日本孰妇毛茸茸xxxx | 日韩精品一区二区三区中文在线 | 欧美精品不卡 | 欧美一级xxx| 求av网站 | 99久久婷婷国产一区二区三区 | 日韩一级不卡 | 国产精品一区二区在线免费观看 | 国产精品成熟老女人 | 久久欧洲| 日韩三级在线免费观看 | 一区二区成人在线观看 | 看片日韩 | 视频在线观看一区 | 国产亲伦免费视频播放 | 影音先锋久久久久av综合网成人 | 久久大胆人体 | 日韩欧美在线观看一区二区三区 | 色久天堂 | 免费日韩在线视频 | 福利在线免费 | 免费中文字幕日韩欧美 | 成人在线观看免费网站 | 五月婷婷丁香网 | 性色av一区二区三区在线观看 | 麻豆三级视频 | 国产在线毛片 | 加勒比一区在线 | 亚洲天堂系列 | 玖玖精品 | 免费在线黄 | 成人免费毛片糖心 | 18黄暴禁片在线观看 | 91精品婷婷国产综合久久蝌蚪 | 国产一区二区三区在线看 | 中日韩毛片| 欧美成本人视频 | 激情高潮呻吟抽搐喷水 | 在线观看日本视频 | 亚洲 欧美 激情 另类 校园 | www.-级毛片线天内射视视 | 国产新婚疯狂做爰视频 | 国产尤物av | av中文在线资源 | 丁香五香天堂 | 亚洲精品九九 | 69亚洲乱人伦 | jzz国产| 久久婷五月 | www在线免费观看 | 国产精品成人久久久久 | 午夜免费片 | 性欧美丰满熟妇xxxx性久久久 | 国产精品毛片久久久久久久 | 999黄色片| 久久成年人| 总裁边开会边做小娇妻h | 亚洲国产欧美在线人成 | 综合久久五月 | 亚洲色欲色欲www在线观看 | 成年人黄视频 | 激情小说图片视频 | 色偷偷888欧美精品久久久 | 奇米狠狠 | 在线中文视频 | a级黄色片免费看 | 91字幕网| 久久综合久久久 | 成人爽a毛片一区二区 | 欧美日韩在线一区二区三区 | 天天干天天操天天摸 | 银杏av| 午夜爱爱免费视频 | 粗大黑人巨茎大战欧美成人 | 免费网站在线观看人数在哪动漫 | 欧av在线| 五月激情网站 | 国产91av在线播放 | 欧美日韩国产亚洲沙发 | 2021亚洲天堂 | 老熟妇一区二区三区啪啪 | 国产综合在线观看 | 午夜在线国产 | 日韩高清一级 | 羞羞羞网站 | 日韩欧美三级在线观看 | 四虎国产精品永久免费观看视频 | 久久精品电影网 | 中文字幕亚洲激情 | 成人高潮片免费网站 | 午夜免费剧场 |