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:顾问
<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:拦截器
底层实现
- 如果目标类有实现接口,使用JDK实现
- 如果目标类没有实现接口,使用CGLib实现
可以通过proxy-target-class 属性修改底层实现方案
true:强制都是CGLib false:默认做法
切入点表达式
- execution
- args
- within
- @annotation
-
- 任意公开方法:execution(public * *(..))
- 名字以set开头的任意方法:execution(* set*(..))
- 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 属性设置事务的传播行为