一、切入点表达式

  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学习基础的更多相关文章

  1. Spring AOP 学习例子

    http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example     工作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大 ...

  2. AOP技术基础

    1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...

  3. AOP技术基础(转)

    1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...

  4. springBoot AOP学习(一)

    AOP学习(一) 1.简介 AOp:面向切面编程,相对于OOP面向对象编程. Spring的AOP的存在目的是为了解耦.AOP可以让一切类共享相同的行为.在OOP中只能通过继承类或者实现接口,使代码的 ...

  5. Spring AOP学习笔记

      Spring提供了一站式解决方案:          1) Spring Core  spring的核心功能: IOC容器, 解决对象创建及依赖关系          2) Spring Web ...

  6. spring 学习(三):aop 学习

    spring 学习(三):aop 学习 aop 概念 1 aop:面向切面(方面)编程,扩展功能不修改源代码实现 2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 3 aop底层使用动态代 ...

  7. Spring入门IOC和AOP学习笔记

    Spring入门IOC和AOP学习笔记 概述 Spring框架的核心有两个: Spring容器作为超级大工厂,负责管理.创建所有的Java对象,这些Java对象被称为Bean. Spring容器管理容 ...

  8. Spring IOC 和Aspectj AOP

    1.Aspectj AOP 是一套独立的AOP 解决方案,不仅限于java应用,不依赖其他方案,属于编译时增强,有自己单独的编译器.Spring AOP 是基于Spring 容器的的AOP解决方式,属 ...

  9. 现代3D图形编程学习-基础简介(2) (译)

    本书系列 现代3D图形编程学习 基础简介(2) 图形和渲染 接下去的内容对渲染的过程进行粗略介绍.遇到的部分内容不是很明白也没有关系,在接下去的章节中,会被具体阐述. 你在电脑屏幕上看到的任何东西,包 ...

随机推荐

  1. ssh相关操作

    连接:ssh username@ip 拷贝ssh客户端文件到ssh服务器: cp 文件名 username@ip:文件名 拷贝ssh服务器文件夹到ssh客户端: scp -r wanglianghe@ ...

  2. C# 无边框窗体边框阴影效果

    通过下面代码在构造函数中调用方法 SetShadow(); 即可实现无边框窗体的阴影效果了 需要添加命名空间 using System.Runtime.InteropServices; private ...

  3. 基于jsp的文件上传和下载

    参考: 一.JavaWeb学习总结(五十)--文件上传和下载 此文极好,不过有几点要注意: 1.直接按照作者的代码极有可能listfile.jsp文件中 <%@taglib prefix=&qu ...

  4. JQuery判断数组中是否包含某个元素$.inArray("js", arr);

    var arr = [ "xml", "html", "css", "js" ];   $.inArray(" ...

  5. xp-win7-win8的基础到精通教程-系统优化减肥教程-windos装mac

    是否还在使用别人封装的系统?是否还在担心下载后的系统是有病毒的?还在为 安装好新系统后,里面安装的软件全是自己不需要的?担心流氓软件绑定浏览器主页?担心 系统重装后,自己所有的编程软件都需要重新安装? ...

  6. IT男的”幸福”生活"续9

    世界上最容易失去的便是时间了,我们总是蓦然回首,而时间早已流去. 曾经的种种,时时刻刻在我们脑中出现,让我们感到开心,快乐,幸福等. 有时好想有一种动冲,回到过去,再感受一下心中的那份触动. 又一年过 ...

  7. Java学习笔记(二十)——Java 散列表_算法内容

    [前面的话] 周末,本来打算找人去玩,结果没找到,所以我只好有学习了. 为什么会学习散列表,因为要使用HashMap?因为在做项目的时候,在服务器和客户端需要传输DTO,而传输的属性是动态增加的,所以 ...

  8. windows API 开发飞机订票系统 图形化界面 (四)

    接下来的是录入航班.修改航班信息功能的实现: //录入航班 BOOL EntryFlight(HWND hEntryDlg){ TCHAR szDiscount[]; TCHAR szFare[],s ...

  9. sublime2的一些基本常用的操作

    1.全局搜 ctrl shift f 如果你的快捷键有冲突的话,那么你在find的菜单中有find in file这个中找.

  10. ubuntu chmod 无法更改 文件夹权限 系统提示“不允许的操作 2、linux 如何修改只读文件 3、ubuntu安装

    1.ubuntu chmod 无法更改 文件夹权限 系统提示“不允许的操作 答案:需要超级用户权限 sudo 2.linux 如何修改只读文件 答案:可以使用chmod命令,为改文件提供其他的权限.u ...