1. 概要

添加类库:aspectjrt.jar和aspectjweaver.jar
添加aop schema.
定义xml元素:<aop:aspectj-autoproxy>
编写java类,并用@Aspect注解成通知

AspectJ 支持
5 种类型的通知注解:

@Before: 前置通知,在方法执行之前执行

@After: 后置通知,在方法执行之后执行

@AfterRunning: 返回通知,在方法返回结果之后执行

@AfterThrowing: 异常通知,在方法抛出异常之后

@Around: 环绕通知,围绕着方法执行

配置成普通bean元素即可.
 

前置通知:@Before

@Aspect

public class AudienceAdvice {

@Before("execution(* WelcomeService.*(..))")

public void takeSeats(){..}

@Before("execution(* WelcomeService.*(..))")

public void turnOffCellphone(JoinPoint jp){..}

JoinPoint参数可访问连接点细节,入方法名和参数等.

jp.getTarget()//目标对象

jp.getThis()//当前的代理对象

jp.getArgs();//方法调用参数

jp.getSignature().getName()//方法签名

后置通知:@After

@After("execution(* *..WelcomeService.*(..))")

public void applaud(){..}

后置通知在目标方法执行完成之后执行.一个切面aspect包含很多通知.

@After

后置通知表明目标方法执行完之后,不论是否抛异常,都会织入该通知.

@AfterReturning

方法返回后通知只在目标方法返回以后执行,若抛异常不执行.

@AfterReturning(pointcut="",returning="res")

public void xxx(Joinput jp,Object res)

在后置通知中可接收到返回值.res即是用来接收返回值的对象.

环绕通知:@Around

@Around("execution(* *..WelcomeService.*(..))")

public void around(ProceedingPointCut jp){..}

注意:可以控制目标方法是否调用,以及返回完全不同的对象,要慎用.

指定优先级:

@Aspect

@Order(0)

public class xxx{...}

加上@Order注解可以指定加入切面的优先级(先后顺序,值越小,优先级越高)

引入通知:

@Aspect

public class MyAspectjIntroduction {

@DeclareParents(value="*..*Service*",

defaultImpl=ModifyDateImpl.class)

private ModifyDate md ;

}

value:指定哪些类可以应用该属性

defaultImpl:指定接口的实现类

典型Aspectj切入点表达式定义:

execution(* cn.itcast.WelcomeServiceImpl.*(..))

execution(public * *..WelcomeServiceImpl.*(..))

execution(public void *..WelcomeServiceImpl.*(..))

execution(public void *..*Service.*(double,double))..

切入点表达式运算(&& || !)

@Pointcut("execution(..) || execution(..)")

2. 示例代码:

Performer.java 演员接口

public interface Performer {
public void show();
}

Singer.java 接口实现

public class Singer implements Performer {
public void show() {
System.out.println("其实我是个演员!");
// String str = null ;
// str.toString();
}
}

Audience.java 观众类, 即通知类

package cn.itcast.spring.aop.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;
import org.aspectj.lang.annotation.Pointcut; /**
* 观众, 需要添加 @Aspect
*/
@Aspect
public class Audience { /**
* 引入通知,
*/
@DeclareParents(value="cn.itcast.spring.aop.aspectj.Singer",defaultImpl=ModifyDateImpl.class)
private ModifyDate md ;
/**
* 定义在切入点, 切入点表达式
*/
//任意返回值 Performer中 任意方法 任意参数
@Pointcut("execution(* cn.itcast.spring.aop.aspectj.Performer.*(..))")
public void perform(){
}
/**
* 坐好
*/
@Before(value="perform()")
public void takeSeat(){
System.out.println("takeSeat");
} /**
* 关机
*/
@Before(value="perform()")
public void turnOffCellphone(JoinPoint jp){
System.out.println(jp.getSignature().getName());
System.out.println(jp.getArgs());
System.out.println(jp.getTarget());
System.out.println(jp.getThis());
System.out.println("turnOffCellphone");
} /**
* returning:指定哪个参数接受方法的返回值
*/
@AfterReturning(pointcut="perform()",returning="ret")
public void applaud(Object ret){
System.out.println("applaud");
System.out.println("ret = " + ret);
} /**
* 退票
* throwing:指定哪个参数接受异常信息
*/
@AfterThrowing(pointcut="perform()",throwing="e")
public void demandMoney(Exception e){
System.out.println("demandMoney");
System.out.println("出事了 " + e.getMessage());
} @After("perform()")
public void goHome(){
System.out.println("goHome");
} /*
* 环绕通知
*/
@Around(value="perform()")
public Object watch(ProceedingJoinPoint pjp){
try {
System.out.println("takeSeat");
System.out.println("turnOffCellphone");
Object o = pjp.proceed();
System.out.println("applaud");
return o;
} catch (Throwable e) {
System.out.println("demandMoney");
}
finally{
System.out.println("goHome");
}
return null ;
}
}

ModifyDate.java 引入通知接口

/**
* 修改日期
*/
public interface ModifyDate {
public void setModifyDate(Date date);
public Date getModifyDate();
}

ModifyDateImpl.java 引入通知实现

public class ModifyDateImpl implements ModifyDate {
private Date date ;
public Date getModifyDate() {
return date;
} public void setModifyDate(Date date) {
this.date = date ;
}
}

aspectj.xml 配置文件

<?xml version="1.0"?>
<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-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">
<!-- 观众通知 -->
<bean id="audience" class="cn.itcast.spring.aop.aspectj.Audience" /> <!-- 歌手 -->
<bean id="singer" class="cn.itcast.spring.aop.aspectj.Singer" /> <!-- 使用aspectj自动产生代理 -->
<aop:aspectj-autoproxy />
</beans>

App.java 测试代码

public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"cn/itcast/spring/aop/aspectj/aspectj.xml");
Performer p = (Performer) ac.getBean("singer");
p.show();
//测试引入通知
((ModifyDate)p).setModifyDate(new Date());
System.out.println(((ModifyDate)p).getModifyDate());
}
}

3. 使用pojo+xml开发aop

基于注解的aspectj声明优先于xml配置.基于xml的配置是spring专有的.aspectj得到越来越多的支持,具备更好的重用性.

其他bean 和 通知类 都不会改变, 只会不再需要用注解, 改用xml文件

pojo.xml 引入通知, 前置 后置 异常通知

<?xml version="1.0"?>
<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-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">
<!-- 观众 -->
<bean id="audience" class="cn.itcast.spring.aop.pojo.Audience" />
<!-- 歌手 -->
<bean id="singer" class="cn.itcast.spring.aop.pojo.Singer" /> <!-- aop配置 -->
<aop:config>
<aop:aspect ref="audience">
<!-- 引入通知 -->
<aop:declare-parents types-matching="cn.itcast.spring.aop.pojo.Singer"
implement-interface="cn.itcast.spring.aop.pojo.ModifyDate"
default-impl="cn.itcast.spring.aop.pojo.ModifyDateImpl"/>
<!-- 单独定义切入点表达式 -->
<aop:pointcut id="audiencePointcut" expression="execution(* cn.itcast.spring.aop.pojo.Performer.*(..))"/> <!-- 前置通知 -->
<aop:before method="takeSeat" pointcut-ref="audiencePointcut" />
<aop:before method="turnOffCellphone" pointcut-ref="audiencePointcut"/> <!-- 后置通知,ret指定哪个参数接受返回值 -->
<aop:after-returning method="applaud" pointcut-ref="audiencePointcut" returning="ret"/> <!-- throwing:指定哪个参数接受异常信息 -->
<aop:after-throwing method="demandMoney" pointcut-ref="audiencePointcut" throwing="ex"/> <!-- -->
<aop:after method="goHome" pointcut-ref="audiencePointcut"/>
</aop:aspect>
</aop:config>
</beans>

pojoAround.xml 环绕通知

<?xml version="1.0"?>
<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-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">
<!-- 观众 -->
<bean id="audience" class="cn.itcast.spring.aop.pojo.AudienceAround" />
<!-- 歌手 -->
<bean id="singer" class="cn.itcast.spring.aop.pojo.Singer" /> <!-- aop配置 -->
<aop:config>
<aop:aspect ref="audience">
<aop:around method="watch" pointcut="execution(* cn.itcast.spring.aop.pojo.Performer.*(..))"/>
</aop:aspect>
</aop:config>
</beans>

Spring -- aop, 用Aspectj进行AOP开发的更多相关文章

  1. Spring框架(6)---AspectJ实现AOP

    AspectJ实现AOP 上一篇文章Spring框架(4)---AOP讲解铺垫,讲了一些基础AOP理解性的东西,那么这篇文章真正开始讲解AOP 通过AspectJ实现AOP要比普通的实现Aop要方便的 ...

  2. 在Spring中使用AspectJ实现AOP

    在Spring中,最常用的AOP框架是AspectJ,使用AspectJ实现AOP有2种方式: 基于XML的声明式AspectJ 基于注解的声明式AspectJ 基于XML的声明式AspectJ 1. ...

  3. spring9——AOP之AspectJ对AOP的实现

    从上述的实验中可以看出BeanNameAutoProxyCreator对于AOP的实现已经和完美了,但是还有两点不足之处: 1,对于切面的实现比较麻烦,既不同类型的通知切面要实现不同的接口,而且一个切 ...

  4. spring3: schema的aop与Aspectj的aop的区别

    schema的aop如下: 接口: package chapter6.service; public interface IHelloAroundService { public void sayAr ...

  5. 第三章 AOP 基于@AspectJ的AOP

    在前面,我们分别使用Pointcut.Advice.Advisor接口来描述切点.增强.切面.而现在我们使用@AdpectJ注解来描述. 在下面的例子中,我们是使用Spring自动扫描和管理Bean. ...

  6. 比较 Spring AOP 与 AspectJ

    本文翻译自博客Comparing Spring AOP and AspectJ(转载:https://juejin.im/post/5a695b3cf265da3e47449471) 介绍 如今有多个 ...

  7. AspectJ对AOP的实现

    一:你应该明白的知识 1.对于AOP这种编程思想,很多框架都进行了实现.Spring就是其中之一,可以完成面向切面编程.然而,AspectJ也实现了AOP的功能,且实现方式更为简捷,使用更加方便,而且 ...

  8. Spring_AOP基于AspectJ的注解开发&JDBC的模板使用&事务管理(学习笔记3)

    一:AOP基于AspectJ的注解开发 1,简单的实例: 1)引入相应的jar包 ​ 2)在配置文件里引入相关约束 <beans xmlns="http://www.springfra ...

  9. [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

随机推荐

  1. iOS 百度地图获取当前地理位置

    // // ViewController.m // BaiDuDemo // // Created by Chocolate. on 15-3-2. // Copyright (c) 2015年 re ...

  2. 《挑战程序设计竞赛》2.6 数学问题-辗转相除法 AOJ0005 POJ2429 1930(1)

    AOJ0005 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0005 题意 给定两个数,求其最大公约数GCD以及最小公倍数LCM. ...

  3. 转+总结!! 关于jsp页面取值方式

    1.      前台往后台传值,通过提交表单,在后台有set,get方法,可以直接取到.如果通过request.getParameter(paramName) 去获取通过会报空指针异常. 其中requ ...

  4. CNI插件实现框架---以loopback为示例

    以最简单的loopback插件作为实例,来分析CNI plugin的执行流程 // cni/plugins/loopback/loopback.go 1.func main() main函数只是简单地 ...

  5. Python高级教程-返回函数

    函数作为返回值 高阶函数除了可以接收函数作为参数外,还可以把函数作为结果值返回. 要实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = 0 ...

  6. Windows下QT MySQL驱动编译

    在Windows环境中使用Qt进行关于MySQL数据库的操作时,会出现如下问题: QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: availa ...

  7. mysql进阶(二)之细谈索引、分页与慢日志

    索引 1.数据库索引 数据库索引是一种数据结构,可以以额外的写入和存储空间为代价来提高数据库表上的数据检索操作的速度,以维护索引数据结构.索引用于快速定位数据,而无需在每次访问数据库表时搜索数据库表中 ...

  8. linux命令行与shell脚本编程 -----15控制脚本

    常见的Linux系统信号 信号 值 描述 1 SIGHUP 挂起进程 2 SIGINT 终止进程 3 SIGQUIT 停止进程 9 SIGKILL 无条件终止进程 15 SIGTERM 可能的话终止进 ...

  9. 17届计算机应届生秋季校招分享 to Tomorrow

    首先自我介绍一下,本人来自普通二本院校,计算机科学与技术专业,在校有一到两年asp.net项目经验,花了两个星期左右的时间转向java.现将此次的求职经历,分为三阶段,分享给大家. First Sta ...

  10. CNN学习笔记:池化层

    CNN学习笔记:池化层 池化 池化(Pooling)是卷积神经网络中另一个重要的概念,它实际上是一种形式的降采样.有多种不同形式的非线性池化函数,而其中“最大池化(Max pooling)”是最为常见 ...