2、PersonImpl类的源码

public class PersonImpl implements Person {
private String name;
private int age; public void setName(String name) {
this.name = name;
} public void setAge(int age) {
this.age = age;
} public void info() {
System.out.println("\t我叫" + name + ",今年" + age + "岁。");
} public void show(String message) {
System.out.println(message);
}
}

3、bean的配置

<!-- 目标对象 -->
<bean id="personTarget" class="com.cjm.aop.PersonImpl">
<property name="name" value="Raymond.chen"/>
<property name="age" value="30"/>
</bean>

二、Spring AOP支持的通知类型

一)环绕通知(Around advice)

实现环绕通知需要实现org.aopalliance.intercept.MethodInterceptor接口。

1、PersonAroundAdvice类的源码

public class PersonAroundAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("AroundAdvice:方法调用前"); //不要忘记调用invocation的proceed方法哦
Object result = invocation.proceed(); System.out.println("AroundAdvice:方法调用后");
return result;
}
}

2、bean配置

<bean id="personAroundAdvice" class="com.cjm.aop.PersonAroundAdvice"/>

<!-- 代理工厂bean -->
<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personAroundAdvice</value>
</list>
</property>
</bean>

3、测试代码

ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");
Person p = (Person)context.getBean("person"); //注意这里是代理工厂Bean的ID
p.info();

二)前置通知(Before advice)

实现前置通知需要实现org.springframework.aop.MethodBeforeAdvice接口。

1、PersonBeforeAdvice类的源码

public class PersonBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("BeforeAdvice:方法调用前");
}
}

2、bean配置

<bean id="personBeforeAdvice" class="com.cjm.aop.PersonBeforeAdvice"/>

<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personBeforeAdvice</value>
</list>
</property>
</bean>

三)返回后通知(After Returning advice)

实现返回后通知需要实现org.springframework.aop.AfterReturningAdvice接口。

1、PersonAfterReturningAdvice类的源码

public class PersonAfterReturningAdvice implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("AfterReturningAdvice:方法调用后");
}
}

2、bean配置

<bean id="personAfterReturningAdvice" class="com.cjm.aop.PersonAfterReturningAdvice"/>

<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personAfterReturningAdvice</value>
</list>
</property>
</bean>

3、以上的配置中,通知对目标对象的所有方法都会起作用。如果需要过滤掉一部分方法,可以用正则表达式切入点配置器或者方法名匹配切入点配置器实现。

<!-- 通知与正则表达式切入点一起配置 -->
<!-- Advisor等于切入点加通知 -->
<!-- 方法名匹配切入点配置器:org.springframework.aop.support.NameMatchMethodPointcutAdvisor -->
<bean id="personPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="personAfterReturningAdvice"/>
<property name="patterns">
<list>
<value>.*info.*</value>
</list>
</property>
</bean> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personPointcutAdvisor</value>
</list>
</property>
</bean>

四)异常通知(Throws advice)

当连接点抛出异常时,异常通知被调用。实现异常通知需要实现org.springframework.aop.ThrowsAdvice接口,该接口不包含任何方法,但在实现该接口时必须实现如下形式的方法:                  afterThrowing([Method], [args], [target], Throwable subclass)           可以实现一个或多个这样的方法。在这些方法中,只有第四个参数是必需的,前三个参数可选。

1、PersonThrowsAdvice类的源码

public class PersonThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(FileNotFoundException ex){
System.out.println("ThrowsAdvice >> FileNotFoundException:" + ex.toString());
} public void afterThrowing(Object[] args, Exception ex){
System.out.println("ThrowsAdvice >> Exception:" + ex.getMessage());
} public void afterThrowing(Method method, Object[] args, Object target, Throwable ex){
System.out.println("ThrowsAdvice >> Throwable:" + ex.getMessage());
}
}

2、bean配置

<bean id="personThrowsAdvice" class="com.cjm.aop.PersonThrowsAdvice"/>

<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personThrowsAdvice</value>
</list>
</property>
</bean>

五)引入通知(Introduction advice)

引入通知是一种特殊的通知,它能将新的成员变量、成员方法引入到目标类中。它不能作用于任何切入点,因为它只作用于类层次,而不是方法层次。实现引入通知需要实现IntroductionAdvisor和IntroductionInterceptor接口。

引入通知不能调用proceed方法。Advisor必须针对每个实例,并且是有状态的。

引入通知的效果类似于设计模式中的访问者模式(Visitor Pattern)。

1、Lockable接口的源码

public interface Lockable {
void lock();
void unlock();
boolean locked();
}

2、LockableImpl类的源码

public class LockableImpl extends DelegatingIntroductionInterceptor implements Lockable {
private boolean locked; public void lock() {
this.locked = true;
} public void unlock() {
this.locked = false;
} public boolean locked() {
return this.locked;
} @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if(this.locked){
throw new RuntimeException("加锁,无法执行");
} //这里不能调用invocation的proceed方法
//通常不需要改写invoke方法,直接调用父类的该方法即可
return super.invoke(invocation);
}
}

3、PersonIntroductionAdvice类的源码

public class PersonIntroductionAdvice extends DefaultIntroductionAdvisor {
public PersonIntroductionAdvice(){
super(new LockableImpl(), Lockable.class);
}
}

4、bean配置

<!-- Advice必须针对每个实例,所以scope要设为prototype -->
<bean id="personIntroductionAdvice" class="com.cjm.aop.introduction.PersonIntroductionAdvice" scope="prototype"/> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personIntroductionAdvice</value>
</list>
</property>
</bean>

5、测试代码

ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");

//获得目标bean的代理bean
Person p = (Person)context.getBean("person"); //执行代理bean的方法,此时并未调用lock方法,可以执行
p.info(); Lockable lockable = (Lockable)p;
lockable.lock(); //目标bean已被锁定,此处将抛出异常
p.info();

Spring AOP使用整理:各种通知类型的介绍的更多相关文章

  1. spring aop的五种通知类型

    昨天在腾讯课堂看springboot的视频,老师随口提问,尼玛竟然回答错了.特此记录! 问题: Spring web项目如果程序启动时出现异常,调用的是aop中哪类通知? 正确答案是: 异常返回通知. ...

  2. spring aop 的五种通知类型

    本文转自:http://blog.csdn.net/cqabl/article/details/46965197 spring aop通知(advice)分成五类: 前置通知[Before advic ...

  3. 十五 Spring的AOP的注解的通知类型,切入点的注解

    Spring的注解的AOP的通知类型 @Before:前置通知 @AfterReturning:后置通知 @Around:环绕通知 @AfterThrowing:异常抛出通知 @After:最终通知 ...

  4. Spring AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)

    1.我所知道的AOP 初看起来,上来就是一大堆的术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下让你不知所措,心想着:管不得很多人都和我说AOP多难多难.当我看进去以后, ...

  5. JAVA框架 Spring AOP--切入点表达式和通知类型

    一:AOP的相关术语: 1)Joinpoint(连接点):所谓的连接点是指那些可以被拦截点,在spring中这些点是指方法.因为在spring中支持方法类型的连接点. 2)Pointcut(切入点): ...

  6. 分享知识-快乐自己:Spring切入点的表达式和通知类型

    1.切入点的表达式 表达式格式: execution([修饰符] 返回值类型 包名.类名.方法名(参数)) 其他的代替: <!-- 完全指定一个方法 --> <!-- <aop ...

  7. Spring AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)(转)

    1.我所知道的AOP 初看起来,上来就是一大堆的术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下让你不知所措,心想着:管不得很多人都和我说AOP多难多难.当我看进去以后, ...

  8. Spring AOP 知识整理

    通过一个多月的 Spring AOP 的学习,掌握了 Spring AOP 的基本概念.AOP 是面向切面的编程(Aspect-Oriented Programming),是基于 OOP(面向对象的编 ...

  9. 7.Spring切入点的表达式和通知类型

    1.切入点的表达式 表达式格式: execution([修饰符] 返回值类型 包名.类名.方法名(参数)) 其他的代替: <!-- 完全指定一个方法 --> <!-- <aop ...

随机推荐

  1. 疯狂位图之——位图实现12GB无重复大整数集排序

    <Programming Pearls>(编程珠玑)第一章讲述了如何用位图排序无重复的数据集,整个思想很简洁,今天实践了下. 一.主要思想 位图排序的思想就是在内存中申请一块连续的空间作为 ...

  2. 开始学习node.js了,第一节,fs文件系统 【fs.rename】重命名文件/文件夹

    var fs=require('fs');fs.rename('c:\\a','c:\\a2',function(err){ if(err) console.log('error:'+err);}); ...

  3. Web API 基于ASP.NET Identity的Basic Authentication

    今天给大家分享在Web API下,如何利用ASP.NET Identity实现基本认证(Basic Authentication),在博客园子搜索了一圈Web API的基本认证,基本都是做的Forms ...

  4. Git.Framework 框架随手记--ORM新增操作

    本篇主要记录具体如何新增数据,废话不多说,开始进入正文. 一. 生成工程结构 上一篇已经说到了如何生成工程结构,这里在累述一次. 1. 新建项目总体结构 使用VS新建项目结构,分层结构可以随意.我们使 ...

  5. Ibatis学习总结5--动态 Mapped Statement

    直接使用 JDBC 一个非常普遍的问题是动态 SQL.使用参数值.参数本身和数据列都 是动态的 SQL,通常非常困难.典型的解决方法是,使用一系列 if-else 条件语句和一连串 讨厌的字符串连接. ...

  6. Docker-2 的创建、启动、终止、删除、迁移等

    学习博客地址:http://www.dwhd.org/20151115_140935.html

  7. BZOJ-4424 &&CodeForces-19E Fairy DP+dfs (Link-Cut-Tree可A)

    Va爷的胡策题T2 E. Fairy time limit per test1.5 seconds memory limit per test256 megabytes inputstandard i ...

  8. android studio中the logging tag can be most 23 characters

    转:http://blog.csdn.net/voiceofnet/article/details/49866047 今天写代码的时候,突然发现平时用的好好的Log竟然报错,提示信息为:the log ...

  9. omnetpp inet

    http://blog.csdn.net/midie/article/details/5086983 omnetpp inet 自带了Mingw编译环境,而不再需要Visual C编译环境了.事实上, ...

  10. Nginx 配置文件详解

    user nginx ; #用户 worker_processes 8; #工作进程,根据硬件调整,大于等于cpu核数 error_log logs/nginx_error.log crit; #错误 ...