Spring02-AOP

87 阅读1分钟

AOP (Aspect Oriented Programming) 面向切面编程,Spring使用AOP技术封装了动态代理的功能,使用起来非常简单。

配置 依赖AspectJ库

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.6</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

MethodBeforeAdvice

实现 MethodBeforeAdvice 接口,用来编写额外功功能 (会在目标方法执行之前执行)

execution:执行

advisor:顾问

image.png

<bean id="logAdvice" class="com.mj.aop.LogAdvice"/>

<aop:config>
    <aop:pointcut id="pc" expression="execution(* *(..))"/>
    <aop:advisor advice-ref="logAdvice" pointcut-ref="pc"/>
</aop:config>

MethodInterceptor

Interceptor:拦截器

image.png

image.png

底层实现

  • 如果目标类有实现接口,使用JDK实现
  • 如果目标类没有实现接口,使用CGLib实现

可以通过proxy-target-class 属性修改底层实现方案

true:强制都是CGLib false:默认做法

image.png

切入点表达式

  • execution
  • args
  • within
  • @annotation
  • 任意公开方法:execution(public * *(..))
  • 名字以set开头的任意方法:execution(* set*(..))

image.png

  • pointcut 语句要在 advisor上面

AOP-事务管理

使用Spring的声明式事务,可以极其容易地进行事务管理

  • 只需要在xml中进行声明配置
  • 一般是在Service层进行事务管理

advice:

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



    <context:property-placeholder location="db.properties"/>

    <!--   数据源(Druid)     -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--  创建sqlSessionFactory  -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--  数据源  -->
        <property name="dataSource" ref="dataSource"/>
        <!--  这个包底下的类会自动设置别名(一般是领域模型)  -->
        <property name="typeAliasesPackage" value="com.mj.domain"/>
        <!--  映射文件的位置  -->
        <property name="mapperLocations">
            <array>
                <value>mappers/*.xml</value>
            </array>
        </property>
    </bean>

    <!--  扫描dao  -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 设置SqlSessionFactoryBean的id -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 设置dao的包 -->
        <property name="basePackage" value="com.mj.dao"/>
    </bean>


    <bean id="skillService" class="com.mj.service.impl.SkillServiceImpl">
        <!--    skillDao 就是扫包而来的    -->
        <property name="dao" ref="skillDao"/>
    </bean>

    <bean id="txMgr" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--  附加代码 (在方法前后增加事务管理代码)  -->
   <tx:advice id="txAdvice" transaction-manager="txMgr">
       <tx:attributes>
           <tx:method name="*" no-rollback-for="RuntimeException"/>
           <tx:method name="list*" propagation="SUPPORTS"/>
       </tx:attributes>
   </tx:advice>

    <aop:config>
        <aop:pointcut id="pc" expression="within(com.mj.service..*)"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
    </aop:config>


</beans>

核心代码

<bean id="txMgr" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource"/>
 </bean>

 <!--  附加代码 (在方法前后增加事务管理代码)  -->
<tx:advice id="txAdvice" transaction-manager="txMgr">
    <tx:attributes>
        <tx:method name="*" no-rollback-for="RuntimeException"/>
        <tx:method name="list*" propagation="SUPPORTS"/>
    </tx:attributes>
</tx:advice>

 <aop:config>
     <aop:pointcut id="pc" expression="within(com.mj.service..*)"/>
     <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
 </aop:config>

切面在那些包里面切

附加代码 是 txAdvice 针对某个方法 进行配置

主配置就是 txMgr

propagation 传播

可以通过 propagation 属性设置事务的传播行为

image.png

read-only

timeout

rollback-for、no-rollback-for