AspectJ AOP学习基础
一、切入点表达式
1、execution:匹配方法的执行
格式:execution(修饰符 返回值类型 包.类.方法(参数) throw 异常)
1.1修饰符,表示方法的修饰符,一般省略。
1.2返回类型 String表示返回String;void表示没有返回值;*表示返回任意类型,包括无返回值。
1.3包
hjp.spring.service 表示指定的包
hjp.spring.*.service 表示spring下子模块包含service的包
hjp.spring.service.. 表示service目录及其子目录
综合:hjp.spring.*.service..
1.4类 UserService表示指定的类;*Service表示以Service结尾;Test*表示以Test开头;*表示任意类名。
1.5方法(与类相似)
addUser表示指定方法;add*表示以add开头;*Do表示以Do结尾;*表示任意。
1.6参数 ()表示没有参数;(int)表示一个int类型参数;(int,int)表示两个int类型参数(如果是java.lang包下的可以省略,其他类型必须写完全限定类名);(..)表示
任意,包括无参。
1.7throws 异常,一般省略。
综合:execution(* hjp.spring.*.service..*.*(..))
2、within:匹配包或子包中的方法,如:within(hjp.spring.service..*)
3、this:匹配实现接口的代理对象中的方法,如:this(hjp.spring.dao.UserDao)
4、target:匹配实现接口的目标对象中的方法,如:target(hjp.spring.daoImpl.UserDao)
5、args:匹配参数格式符合标准的方法,如args(int,int)
6、bean:匹配指定的bean,如:bean("userServiceId")
二、AspectJ规定的通知类型
1、before:前置通知(应用:各种校验),在方法执行前执行,如果通知抛出异常,阻止方法运行。
2、afterReturning:后置通知(应用:常规数据处理),方法正常返回后执行,如果方法中抛出异常,通知无法执行;在方法执行后执行,所以才可以获得方法的返回值。
3、around:环绕通知(应用:可以做任何事),方法执行前后分别执行,可以阻止方法的执行。
4、afterThrowing:抛出异常通知(应用:包装异常信息),方法抛出异常后执行,如果方法没有抛出异常,无法执行。
5、after:最终通知(应用:清理现场),方法执行完毕后执行,无论方法是否有异常出现。
环绕通知类似代码块:
try{
//前置通知(before)
//手动执行目标方法
//后置通知(after),可获得返回值
}catch{
//抛出异常通知(afterThrowing),可获得具体异常信息
}finally{
//最终(finally)
}
环绕通知类似代码块
三、基于XML配置的代码示例
1、代码结构:

2、aspectj aop不是针对接口的,所有有没有接口不影响AOP实现,下面是UserService接口和UserServiceImpl实现类(目标类)代码
package hjp.springAOP.springAspectJXml;
public interface UserService {
void addUser();
void updateUser();
}
UserService
package hjp.springAOP.springAspectJXml;
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("aspectj xml add user");
}
@Override
public void updateUser() {
// TODO Auto-generated method stub
//int i=9/0;
System.out.println("aspectj xml update user");
}
}
UserServiceImpl
3、切面类MyAspect代码
package hjp.springAOP.springAspectJXml; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; public class MyAspect {
public void myBefore(JoinPoint joinPoint) {
System.out.println("前置通知:" + joinPoint.getSignature().getName());
} public void myAfterReturning(JoinPoint joinPoint, Object ret) {
System.out.println("后置通知:方法名," + joinPoint.getSignature().getName() + ";返回值," + ret);
} public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知前");
// 手动执行目标方法
Object object = proceedingJoinPoint.proceed();
System.out.println("环绕通知后");
return object;
} public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("目标类方法" + joinPoint.getSignature().getName() + "抛出异常:" + e.getMessage());
} public void myAfter(JoinPoint joinPoint) {
System.out.println("最终执行通知:方法:" + joinPoint.getSignature().getName());
}
}
MyAspect
4、beans.xml配置文件,记得添加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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1、创建目标类 -->
<bean id="userServiceId" class="hjp.springAOP.springAspectJXml.UserServiceImpl"></bean>
<!-- 2、创建切面类 (通知) -->
<bean id="myAspectId" class="hjp.springAOP.springAspectJXml.MyAspect"></bean>
<!-- aop编程
如果强制使用CGLIB,则设置aop:config 属性proxy-target-class="true"
-->
<aop:config>
<!-- aspectj 编程
ref指向切面类 -->
<aop:aspect ref="myAspectId">
<!-- 声明切入点,确定目标类上哪些方法需被增强 -->
<aop:pointcut expression="execution(* hjp.springAOP.springAspectJXml.*.*(..))" id="myPointCut" />
<!-- 声明通知方式 -->
<!-- 1、前置通知
method切面类中具体方法名
pointcut-ref指向切入点(使用pointcut,也可以在通知里配置自己的切入点表达式)
<aop:before method="myBefore" pointcut-ref="myPointCut"/>
-->
<!-- 2、后置通知,可获取到返回值
returning用于设置通知的第二个参数名称,类型为Object(注意:此处参数名称要与切面类后置通知方法第二个参数名称一致)
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret"/>
-->
<!-- 3、环绕通知
<aop:around method="myAround" pointcut-ref="myPointCut"/>
-->
<!-- 4、抛出异常通知(测试此通知时,将目标类中updateUser方法中int i=9/0;代码注释去掉)
目标方法在抛出异常时执行,如果没有则不执行
throwing设置抛出异常通知的第二个参数,参数名称和此处设置的e一致,类型Throwable
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
-->
<!-- 5、最终通知,即任何情况下都会执行 -->
<aop:after method="myAfter" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>
beans.xml
5、测试类
package hjp.springAOP.springAspectJXml; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApp {
@Test
public void demo1() {
String xmlPath="hjp/springAOP/springAspectJXml/beans.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService)applicationContext.getBean("userServiceId");
userService.addUser();
userService.updateUser();
}
}
测试类
四、基于注解的代码示例
1、代码结构和上面差不多

2、目标类的接口代码不变,目标类加注解后代码:
package hjp.springAOP.springAspectJAnnotation;
import org.springframework.stereotype.Service;
@Service("userServiceId")//<bean id="userServiceId" class="hjp.springAOP.springAspectJAnnotation.UserServiceImpl"></bean>
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("aspectj xml add user");
}
@Override
public void updateUser() {
// TODO Auto-generated method stub
//int i=9/0;
System.out.println("aspectj xml update user");
}
}
目标类
3、切面类加注解后代码(注意:代码里面使用了引用公共切入点表达式的方法):
package hjp.springAOP.springAspectJAnnotation; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; @Component//<bean id="myAspectId" class="hjp.springAOP.springAspectJAnnotation.MyAspect"></bean>
@Aspect//<aop:aspect ref="myAspectId">
public class MyAspect {
//@Before("execution(* hjp.springAOP.springAspectJAnnotation.*.*(..))")//<aop:before method="myBefore" pointcut="myPointCut"/>
public void myBefore(JoinPoint joinPoint) {
System.out.println("前置通知:" + joinPoint.getSignature().getName());
}
//@AfterReturning(value="execution(* hjp.springAOP.springAspectJAnnotation.*.*(..))",returning="ret")
public void myAfterReturning(JoinPoint joinPoint, Object ret) {
System.out.println("后置通知:方法名," + joinPoint.getSignature().getName() + ";返回值," + ret);
}
//编写共有的切入点表达式
@Pointcut("execution(* hjp.springAOP.springAspectJAnnotation.*.*(..))")
private void myPointCut(){}
//@Around("myPointCut()")//注意加括号
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知前");
// 手动执行目标方法
Object object = proceedingJoinPoint.proceed();
System.out.println("环绕通知后");
return object;
}
//@AfterThrowing(value="myPointCut()",throwing="e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("目标类方法" + joinPoint.getSignature().getName() + "抛出异常:" + e.getMessage());
}
@After("myPointCut()")
public void myAfter(JoinPoint joinPoint) {
System.out.println("最终执行通知:方法:" + joinPoint.getSignature().getName());
}
}
切面类
4、beans.xml配置文件,注意新加context和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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- spring注解扫描 -->
<context:component-scan base-package="hjp.springAOP.springAspectJAnnotation"></context:component-scan>
<!-- 使AOP注解生效 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
5、测试类
package hjp.springAOP.springAspectJAnnotation; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApp {
@Test
public void demo1() {
String xmlPath="hjp/springAOP/springAspectJAnnotation/beans.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService)applicationContext.getBean("userServiceId");
userService.addUser();
userService.updateUser();
}
}
测试类
3、
AspectJ AOP学习基础的更多相关文章
- Spring AOP 学习例子
http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example 工作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大 ...
- AOP技术基础
1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...
- AOP技术基础(转)
1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...
- springBoot AOP学习(一)
AOP学习(一) 1.简介 AOp:面向切面编程,相对于OOP面向对象编程. Spring的AOP的存在目的是为了解耦.AOP可以让一切类共享相同的行为.在OOP中只能通过继承类或者实现接口,使代码的 ...
- Spring AOP学习笔记
Spring提供了一站式解决方案: 1) Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系 2) Spring Web ...
- spring 学习(三):aop 学习
spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...
- Spring入门IOC和AOP学习笔记
Spring入门IOC和AOP学习笔记 概述 Spring框架的核心有两个: Spring容器作为超级大工厂,负责管理.创建所有的Java对象,这些Java对象被称为Bean. Spring容器管理容 ...
- Spring IOC 和Aspectj AOP
1.Aspectj AOP 是一套独立的AOP 解决方案,不仅限于java应用,不依赖其他方案,属于编译时增强,有自己单独的编译器.Spring AOP 是基于Spring 容器的的AOP解决方式,属 ...
- 现代3D图形编程学习-基础简介(2) (译)
本书系列 现代3D图形编程学习 基础简介(2) 图形和渲染 接下去的内容对渲染的过程进行粗略介绍.遇到的部分内容不是很明白也没有关系,在接下去的章节中,会被具体阐述. 你在电脑屏幕上看到的任何东西,包 ...
随机推荐
- 第二章 下山遇虎(@helper)
@helper方法定义 使用@helper关键字可以定义一个方法,这样就可以在页面中调 用这个方法了,和C#中的方法一样.在页面中定义的方法可以访问ViewBag,HttpContext等等页面的属性 ...
- swift 判断输入的字符串是否为数字
// 判断输入的字符串是否为数字,不含其它字符 func isPurnInt(string: String) -> Bool { let scan: Scanner = Scanner(stri ...
- 本地环境,Ecshop安装教程
最近有个项目需要用ECshop来做,之前没接触过ECshop,今天去网上找了下安装教程,现在发出来分享一下. 1. ecshop网店系统最新版本是ECSHOP V2.7.3,去官网下载utf8和gbk ...
- Sublime 将 Tab 转为空格
最近在使用 vue-cli 搭建项目,但每次用 Hbuilder 编写 vue 文件的时候,如果存在<script>部分就会报错,错误信息大意是说空格有问题.仔细研究了之后才知道,这是因为 ...
- The ServiceClass object does not implement the required method in the following form: OMElement sayHello(OMElement e)
今天遇到一件诡异的事情,打好的同一个aar包,丢到测试环境tomcat,使用soapui测试,正常反馈结果. 丢到本地tomcat,使用soapui测试,始终报以下错误. <soapenv:En ...
- php基础22:上传并且保存文件
<?php /* 文件上传的限制 && 保存被上传的文件 在这个脚本中,我们增加了对文件上传的限制.用户只能上传 .gif 或 .jpeg 文件,文件大小必须小于 20 kb: ...
- HttpClient, 使用C#操作Web
我们知道, .Net类库里提供了HttpWebRequest等类,方便我们编程与Web服务器进行交互. 但是实际使用中我们经常会遇到以下需求,基础类里没有直接提供相应的功能(WebClient类包含这 ...
- bt协议详解 DHT篇(上)
bt协议详解 DHT篇(上) 最近开发了一个免费教程的网站,突然产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的 ...
- 内置模块加载器(commonjs规范)的使用
index9.html <html><head> <title>模块加载器</title> <script src="jquery-1. ...
- 扫描函数sweep
groot.sweep(element,vm); element 为要扫描的代码片段,vm 对应的一个 groot.view 定义的 一个Vm的整体 扫面代码 groot.sweep = functi ...