切入点表达式说明
匹配方法的执行(常用)
execution(表达式)
表达式语法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
写法说明:
- 全匹配方式:
public void org.cjw.service.impl.CustomerServiceImpl.saveCustomer() - 访问修饰符可以省略
void org.cjw.service.impl.CustomerServiceImpl.saveCustomer() - 返回值可以使用号,表示任意返回值
` org.cjw.service.impl.CustomerServiceImpl.saveCustomer()` - 包名可以使用号,表示任意包,但是有几级包,需要写几个:
* *.*.*.*.CustomerServiceImpl.saveCustomer() - 使用
..来表示当前包,及其子包* org..CustomerServiceImpl.saveCustomer() - 类名可以使用号,表示任意类
` org..*.saveCustomer()` - 方法名可以使用号,表示任意方法
` org...()` - 参数列表可以使用,表示参数可以是任意数据类型,但是必须有参数
` org...(*)` - 参数列表可以使用
..表示有无参数均可,有参数可以是任意类型* org..*.*(..) - 全通配方式:
* *..*.*(..)
基于XML配置AOP
首先介绍通过XML的方式配置AOP。
搭建环境
第一步:创建一个Java项目
需求:编写一个切面类,在执行insert,update方法,分别在方法执行前、执行后、异常出现后、调用编写统一处理的代码。
—创建一个Java项目,加入Spring框架的基础支持包。

第二步:编写业务层类和接口
UserService 接口
public interface UserService {void insert();void update();}
业务层UserServiceImpl 实现类
public class UserServiceImpl implements UserService {@Overridepublic void insert() {System.out.println("执行了service层的insert方法");}@Overridepublic void update() {System.out.println("执行了service层的update方法");}}
第三步:编写Spring配置文件
引入aop的命名空间
<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 配置UserService --><bean id="userService" class="org.cjw.service.impl.UserServiceImpl" /></beans>
第四步:测试
—测试代码
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext.xml")public class UserServiceTest {@Resource(name = "userService")private UserService userService;@Testpublic void testInsert() {userService.insert();}@Testpublic void testUpdate() {userService.update();}}
—测试结果

配置AOP
第一步:加入AOP的支持包
AOP 思想必须使用AspectJ语法,而AOP思想不是Spring框架设计出来的,而是叫一个AOP联盟组织提出这种思想,所以开发者需要导入AOP联盟提供的 aspectj.weaver.jar(aspectweaver织入包)。

第二步:编写一个切面类
public class TransactionMangerHandler {// 前置增强public void begin() {System.out.println("开启事务");}// 后置增强public void commit() {System.out.println("提交事务");}// 异常增强public void rollback() {System.out.println("回滚事务");}// 最终增强public void closeSession() {System.out.println("关闭session");}}
第三步:配置AOP配置
<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 配置UserService --><bean id="userService" class="org.cjw.service.impl.UserServiceImpl" /><!-- 配置事务管理器 --><bean id="txManger" class="org.cjw.proxyHandler.TransactionMangerHandler" /><!-- 配置aop --><aop:config><!-- 配置切面 --><aop:aspect ref="txManger"><!-- 配置切入点:哪些类中的哪些方法需要做增强(where) --><aop:pointcut id="pt" expression="execution(* org.cjw.service..*.*(..))" /><!-- 前置增强 --><aop:before method="begin" pointcut-ref="pt" /><!-- 后置增强 --><aop:after-returning method="commit" pointcut-ref="pt" /><!-- 异常增强 --><aop:after-throwing method="rollback" pointcut-ref="pt" /><!-- 最终增强 --><aop:after method="closeSession" pointcut-ref="pt" /></aop:aspect><!-- 织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(该过程由Spring来完成)--></aop:config></beans>
第四步:测试
测试代码
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext.xml")public class UserServiceTest {@Resource(name = "userService")private UserService userService;@Testpublic void testInsert() {userService.insert();}@Testpublic void testUpdate() {userService.update();}}
测试结果

思考
问题:编写一个切面需要分别编写前置增强、后置增强、异常增强、最终增强,需要使用到4个标签,有没有办法只用一个标签就完成这4种增强呢?
答:使用环绕增强<aop:aorund>
改写切面类
public class TransactionMangerHandler {// 环绕增强public void allInOne(ProceedingJoinPoint pjp) {try {begin(); // 前置增强pjp.proceed(); // 执行被调用的方法commit(); // 后置增强} catch (Throwable e) {e.printStackTrace();rollback(); // 异常增强} finally {closeSession(); // 最终增强}}// 前置增强public void begin() {System.out.println("开启事务");}// 后置增强public void commit() {System.out.println("提交事务");}// 异常增强public void rollback() {System.out.println("回滚事务");}// 最终增强public void closeSession() {System.out.println("关闭session");}}
—aop配置
<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 配置UserService --><bean id="userService" class="org.cjw.service.impl.UserServiceImpl" /><!-- 配置事务管理器 --><bean id="txManger" class="org.cjw.proxyHandler.TransactionMangerHandler" /><!-- 配置aop --><aop:config><!-- 配置切面 --><aop:aspect ref="txManger"><!-- 配置切入点:哪些类中的哪些方法需要做增强(where) --><aop:pointcut id="pt" expression="execution(* org.cjw.service..*.*(..))" /><!-- 环绕增强 --><aop:around method="allInOne" pointcut-ref="pt" /></aop:aspect><!-- 织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(该过程由Spring来完成)--></aop:config></beans>
测试代码
同上
测试结果

常用标签说明
- 2.4.1.
**<aop:config>**
作用:用于声明aop配置
- 2.4.2.
**<aop:aspect>**
作用: 用于配置切面。
属性:
- id:给切面一个唯一标识。- ref:引用配置好的切面类bean的id。
- 2.4.3.
<aop:pointcut>
作用:用于配置切入点表达式
属性:
- id:用于给切入点表达式一个唯一标识。- expression:用于定义切入点表达式。
- 2.4.4.
<aop:before>
作用:用于配置前置通知
属性:
- method:指定通知中方法的名称。- pointct:定义切入点表达式- pointcut-ref:指定切入点表达式的引用
- 2.4.5.
<aop:after-returning>
作用:用于配置后置通知,如果出了异常就一定不会调用切面的方法
属性:
- method:指定通知中方法的名称。- pointct:定义切入点表达式- pointcut-ref:指定切入点表达式的引用
- 2.4.6.
<aop:after-throwing>
作用: 用于配置异常通知,只有出了异常才会调用切面对应的方法
属性:
- method:指定通知中方法的名称。- pointct:定义切入点表达式- pointcut-ref:指定切入点表达式的引用
- 2.4.7.
<aop:after>
作用:用于配置最终通知,不管出不出异常,都调用切面的方法
属性:
- method:指定通知中方法的名称。- pointct:定义切入点表达式- pointcut-ref:指定切入点表达式的引用
- 2.4.8.
<aop:around>
作用:用于配置环绕通知
属性:
- method:指定通知中方法的名称。- pointct:定义切入点表达式- pointcut-ref:指定切入点表达式的引用
基于注解配置AOP
接下来介绍基于注解的方式配置AOP。
搭建环境
第一步:创建一个Java项目
同上。
第二步:创建UserService接口及其实现类
public interface UserService {void insert();void update();}@Servicepublic class UserServiceImpl implements UserService {@Overridepublic void insert() {System.out.println("执行了service层的insert方法");}}
第三步:编写Spring配置类
@Configuration@ComponentScan(basePackages = "org.cjw")public class SpringConfig {}
第四步:测试
测试代码
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = SpringConfig.class)public class UserServiceTest {@Autowired@Qualifier("userService")private UserService userService;@Testpublic void testInsert() {userService.insert();}}
测试结果

配置AOP
第一步:加入AOP的支持包
—注意:必须要导入加入支持AOP的包。
Spring的AOP包基于AspectJ框架,所以必须加入AspectJ—>aspectjweaver.jar。
第二步:编写一个切面类
@Component@Aspectpublic class TransactionMangerHandler {// 环绕增强@Around("pointcut()")public void allInOne(ProceedingJoinPoint pjp) {try {begin(); // 前置增强pjp.proceed(); // 执行被调用的方法commit(); // 后置增强} catch (Throwable e) {e.printStackTrace();rollback(); // 异常增强} finally {closeSession(); // 最终增强}}@Pointcut("execution(* org.cjw..*.*(..))") // 等价于<aop:pointcut id="等价于方法名" expression="execution(* org.cjw..*.*(..))">public void pointcut() {}// 前置增强@Before("pointcut()") // 等价于<aop:before method="begin" pointcut-ref="pt" />public void begin() {System.out.println("开启事务");}// 后置增强@AfterReturning("pointcut()") // 等价于<aop:after-returning method="commit" pointcut-ref="pt" />public void commit() {System.out.println("提交事务");}// 异常增强@AfterThrowing("pointcut()") // 等价于<aop:after-throwing method="rollback" pointcut-ref="pt" />public void rollback() {System.out.println("回滚事务");}// 最终增强@After("pointcut()") // 等价于<aop:after method="closeSession" pointcut-ref="pt" />public void closeSession() {System.out.println("关闭session");}}
第三步:配置AOP配置
@Configuration@ComponentScan(basePackages = "org.cjw")@EnableAspectJAutoProxy // 开启注解配置AOPpublic class SpringConfig {}
第四步:测试
—测试代码
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = SpringConfig.class)public class UserServiceTest {@Autowired@Qualifier("userService")private UserService userService;@Testpublic void testInsert() {userService.insert();}}
测试结果

常用注解
- @Aspect
作用:把当前类声明为切面类。
- @Before
作用:把当前方法看成是前置通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
- @AfterReturning
作用:把当前方法看成是最终通知。报异常,就不执行。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
- @AfterThrowing
作用:把当前方法看成是异常通知。只有报异常才执行
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
例子:

- @After
作用:把当前方法看成是后置通知。不管报不报异常都执行
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
- @Around
作用:把当前方法看成是环绕通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
- @Pointcut
作用:指定切入点表达式
属性:
综合例子
@Aspect@Componentpublic class NotVeryUsefulAspect {@AfterReturning(value="execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(..))")private void logReceiver(){System.out.println("切入点logReceiver...");}@Pointcut(value="execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(..)) && args(param)")private void pointcut(String param){System.out.println("切入点pointcut()"+param);}//方法体将不执行@Pointcut("within(com.cn.spring.aspectj.*)")public String inWebLayer() {System.out.println("切入点inWebLayer()");return "返回值加载";}@Before(value="inWebLayer()")private void beforeinWebLayer(){System.out.println("beforeinWebLayer~~");}@Before(value="pointcut(param)")private void beforePointcut(String param){System.out.println("beforePointcut:"+param);}@AfterReturning(pointcut="inWebLayer()",returning="retVal")public void doAccessCheck(Object retVal) {System.out.println("doAccessCheck:"+retVal);}@Around(value="execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(..))")private Object aroundLayer(ProceedingJoinPoint pjp) throws Throwable{// start stopwatchObject retVal = pjp.proceed();// stop stopwatchSystem.out.println("aroundLayer~~");return retVal;}}
Spring AOP使用小结
Spring AOP xml配置
(1) 在xml配置文件中引入新的aop命名空间。
(2) Springaop XML配置标签
<aop:config> 开启aop配置,aop所有配置都在此标签内部配置
<aop:ponitcut exepression=”切入点语法” id=””>配置切入点<aop:apect ref=”引入要增强的bean(事务管理器)” >配置切面a.
<aop:before>前置通知
b.<aop:aftereturning>后置通知
c.<aop:afterthrowing>异常通知
d.<aop:after>最终通知
e.<aop:around>环绕通知
Spring AOP 注解配置
(1) 在配置文件/配置类开启注解配置。
① xml:`<aop:aspectj-autoproxy/>`<br /> ② annotation:在java配置类中贴上`@EnableAspectJAutoProxt`注解,作用等同于在xml配置文件中编写`<aop:aspectj-autoproxy>`
(2) @Aspect 在类贴上这个注解,把对应的类当前切面配置类。
(3) @Pointcut 切入点注解
(4)@Before前置通知注解
(5)@After 后置通知注解
(6)@Aftertrhowing异常通知注解
(7)@Afterreturing 最终通知注解
(8) @Around环绕通知注解
