1. 程式人生 > 其它 >spring-aop-事務-註解開發-代理

spring-aop-事務-註解開發-代理

1.spring + mybatis:

Aop流程:

提前定義好幾個用於Aop的類

前置通知:新建MyBeForeAdvice類 實現 MethodBeforeAdvice,並實現其方法

後置通知:新建MyAfterAdvice類 實現 AfterReturningAdvice,並實現其方法

環繞通知:新建RoundAdvice類 實現 MethodInterceptor ,並實現其方法

異常通知:新建ExceptionAdvice類 實現 ThrowsAdvice , 並編寫 ”afterThrowing“ 方法,如下:

public void afterThrowing(Exception ex){
    System.out.println("異常通知: my throws 異常通知輔助功能");
}

applicationContext.xml配置如下:

<!-- 目標 : 原始業務,自己的某個bean都行-->
<bean id="us" class="com.qf.service.UserServiceImpl" />

<!-- 通知:額外功能 -->
<!-- 前置通知類 -->
<bean id="before" class="com.qf.aop.MyBeforeAdvice"></bean>
<!-- 後置通知,在核心之後執行,如果核心有異常,則不執行 -->
<bean id="after" class="com.qf.aop.MyAfterAdvice"></bean>
<!-- 在核心中拋異常時,執行 -->
<bean id="throws" class="com.qf.aop.MyThrowsAdvice"></bean>
<!-- 環繞通知 -->
<bean id="mi" class="com.qf.aop.MyMethodInterceptor"></bean>

定義切入點,形成切面

<aop:config>
    <!-- 切入點【修飾符  返回值  包.類  方法名  引數表 】 -->
    <aop:pointcut id="pc_shine" expression="execution(* queryUsers())"/>
    <aop:pointcut id="pc_shine2" expression="execution(* deleteUser(..))"/>
    <aop:pointcut id="pc_shine3" expression="execution(* updateUser(..))"/>
    <aop:pointcut id="pc_shine4" expression="execution(* saveUser(..))"/>
    
    <!-- 組裝 -->
    <aop:advisor advice-ref="before" pointcut-ref="pc_shine"/>
    <aop:advisor advice-ref="after" pointcut-ref="pc_shine2"/>
    <aop:advisor advice-ref="throws" pointcut-ref="pc_shine3"/>
    <aop:advisor advice-ref="mi" pointcut-ref="pc_shine4"/>
</aop:config>
根據表示式通配切入點:

語法 : execution(返回值型別 包名.方法名(引數包名.型別))

<aop:config>
    <!--匹配引數-->
    <aop:pointcut id="pc01" expression="execution(* *(com.qf.pojo.User))"/>
    <!--匹配任意方法(無參)-->
    <aop:pointcut id="pc02" expression="execution(* *())"/>
    <!--匹配方法名(任意引數)-->
    <aop:pointcut id="pc03" expression="execution(* saveUser(..))"/>
    <!--匹配返回值型別(任意引數)-->
    <aop:pointcut id="pc04" expression="execution(java.lang.Integer *(..))"/>
    <!--匹配類名(任意引數)-->
    <aop:pointcut id="pc05" expression="execution(* com.qf.service.UserServiceImpl.*(..))"/>
    <!--匹配包名(任意引數)-->
    <aop:pointcut id="pc06" expression="execution(* com.qf.service.*.*(..))"/>
    <!--匹配包名、以及子包名(任意引數)-->
    <aop:pointcut id="pc07" expression="execution(* com..*.*(..))"/>

    <!--組裝-->
    <aop:advisor advice-ref="after" pointcut-ref="pc01"/>
</aop:config>

2.事務控制:

1.配置DataSourceTransactionManager事務管理器,其中持有DataSource,可以控制事 務功能(commit,rollback等)。

<!-- 1. 引入一個事務管理器,其中依賴DataSource,藉以獲得連線,進而控制事務邏輯 -->
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

2.配置事務切面, 事務使用的規則

<!--aop在事務中的使用, 配置事務切面, 事務使用的規則-->
<tx:advice id="txManager" transaction-manager="tx">
    <tx:attributes>
        <!--規定哪些方法不需要事務(查詢方法)propagation="SUPPORTS"  取消事務-->
        <tx:method name="find*" propagation="SUPPORTS"/>
        <tx:method name="query*" propagation="SUPPORTS"/>
        <tx:method name="select*" propagation="SUPPORTS"/>
        <tx:method name="get*" propagation="SUPPORTS"/>
        <!--規定哪些方法需要事務(增刪改) rollback-for="Exception" 遇到異常執行回滾操作-->
        <tx:method name="insert*" rollback-for="Exception"></tx:method>
        <tx:method name="update*" rollback-for="Exception"></tx:method>
        <tx:method name="delete*" rollback-for="Exception"></tx:method>
    </tx:attributes>
</tx:advice>

3.將事務管理的Advice 切入需要事務的業務方法中

<!--使用AOP切入事務-->
<aop:config>
    <!--規定切點(某個方法,或匹配範圍內的方法)-->
    <aop:pointcut id="pc" expression="execution(* com.qf.service.*.*(..))"/>
    <!--組織切面-->
    <aop:advisor advice-ref="txManager" pointcut-ref="pc"/>
</aop:config>

3.開啟註解開發

<!--開啟註解使用(掃描此包下的所有註解)-->
<context:component-scan base-package="com.qf"></context:component-scan>
@Autowhrid與@Resource的區別

一個介面只有一個實現類的時候,用@Autowhird

一個人介面有多個實現類的時候,

bean的註解後面應加上括號,例如@Service(value = “u2”)

注入時用@Resource(name = "u2"),而不是@Autowhird

@Controller 用在控制層的實現類上

@Service 用在service實現類上

@Repository 用在dao層的實現類上

@Component 用在其他需要被spring管理的bean上

@Value("${某個屬性名}") //獲取引入的properties檔案內的某個屬性,賦值給變數

private String ha;

4.使用註解@Transactional控制事務 (方便)

  1. 在applicationContext.xml中配置好事務管理器,上面有配置方法

  2. 在applicationContext.xml中配置宣告式事務標籤,並指定事務管理器

  3. <!--宣告式事務,註解實現-->
    <!-- 告知spring,@Transactional在定製事務時,基於tx=DataSourceTransactionManager -->
    <tx:annotation-driven transaction-manager="tx"/>
    
  4. 在applicationContext.xml中配置好註解掃描,上面有配置方法

  5. 在想新增事務的方法上新增@Transactional註解即可

(事務控制應該在ServiceImpl層實現,而不是controller層)