原文地址:http://www.cnblogs.com/zuoxiaolong/p/spring6.html

自己整理后,供自己学习方便:

目前由AOP联盟给出了AOP的标准,AOP联盟的规范只是提供了几个接口定义,为了统一AOP的标准,下面来看看主要的几个接口。

Advice接口:

这是一个空接口,里面没有任何方法,只是用来标识一个通知,在spring中,所有的advice都是此接口的扩展,比如BeforeAdvice,AfterAdvice等。

Interceptor接口:

Advice的子接口,这个接口和advice都不直接使用,一般是要扩展以后去实现特殊的拦截。

Joinpoint接口:

代表了一个运行时的连接点。

Invocation接口:

代表了程序中的一个调用,可以被拦截器Interceptor拦截。

下面还有几个接口,不再一一介绍,从下一层继承开始,interpretor的继承体系已经开始依赖于invocation。这从某种意义上来说,advice是依赖于joinpoint的,但这并非绝对。

下面给出这几个接口的UML图,关系比较清晰。

下面介绍下spring中的AOP核心接口。

Advice体系:

Spring采用AOP联盟的Advice作为超级接口,扩展了很多子接口,比如BeforeAdvice,AfterAdvice等等,稍后以AfterReturningAdvice为例,讨论下spring的通知体系。

Pointcut接口:

spring采用Pointcut作为切点的抽象,其中有一个方法返回一个MethodMatcher,作用很明显,就是说切点决定了要切入哪些方法。这里其实是定义了一个匹配规则。比如正则匹配,可以只匹配前缀为save的方法等等。

Advisor:

通知器或者说通知者,我们从现实角度来说,通知者当然需要知道要通知什么。所以Advisor依赖于Advice,而Advisor旗下的子接口 PointAdvisor还依赖于Pointcut,也就是说这个接口更确切的定位应该是包含了要通知谁和要通知什么,也就是说要能获得Advice和 Pointcut。

下面我们先用一个例子说明spring的AOP 是如何工作的,在spring的bean中有一种特殊的bean,叫FactoryBean。这并不是一个普通的bean,而是用来产生bean的一个 bean。这样说起来有点绕口,但这个接口就是用来做这个事的,它是为了实现一系列特殊加工过的bean而产生的接口。

比如AOP中,我们其实就是要对一个bean进行增强,进行加工,让它在运行的过程中可以做一些特殊的事情。

ProxyFactoryBean就是一个为了AOP实现的特殊的FactoryBean,它的作用很明显就是产生proxy的bean,也就是被我们增强过的bean,在这里给出它的源码。

 public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware { /**
* This suffix in a value in an interceptor list indicates to expand globals.
*/
public static final String GLOBAL_SUFFIX = "*"; protected final Log logger = LogFactory.getLog(getClass()); private String[] interceptorNames; private String targetName; private boolean autodetectInterfaces = true; private boolean singleton = true; private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance(); private boolean freezeProxy = false; private transient ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader(); private transient boolean classLoaderConfigured = false; private transient BeanFactory beanFactory; /** Whether the advisor chain has already been initialized */
private boolean advisorChainInitialized = false; /** If this is a singleton, the cached singleton proxy instance */
private Object singletonInstance;

在这里,一样没有贴出全部的源码,我们主要关心它的属性,其中interpretorNames和targetName就是这个类最主要的属性,前者代表 的是需要加强哪些东西以及需要怎样加强,也就是advice和pointcut。而后者代表的则是我们针对谁来做这些加强,即我们的目标对象。

这里面的增强比较灵活,我来说一下需要的属性。

1.首先interpretorNames是必须赋予的属性,这个属性指定了通知器或者是通知的名字。如果传入的是通知Advice,则会被自动包装为通知器。

2.targetName是我们要增强的目标对象,这个对象如果有实现的接口,则会采用JDK的动态代理实现,否则将需要第三方的jar包cglib。

下面给出一段代码,来测试一下这种增强方式。首先我们需要一个bean.xml的配置文件,去配置这些属性。这样就将IOC和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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="testAop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName">
<value>testTarget</value>
</property>
<property name="interceptorNames">
<value>testAdvisor</value>
</property>
</bean>
<bean id="testTarget" class="org.mj.springTest.aopTest.TestTarget"></bean>
<bean id="testAdvisor" class="org.mj.springTest.aopTest.TestAdvisor"></bean>
</beans>

下面我们看看目标对象的源码。

 /**
* @author jing.ming
* @version 创建时间:2015年10月28日 下午4:35:44
* 程序的简单说明
*/
public class TestTarget { public void test(){
System.out.println("target.test()");
}
public void test2(){
System.out.println("target.test2()") ;
}
}

很简单,只有两个普通的方法,下面我们看通知器的源码。

 /**
* @author jing.ming
* @version 创建时间:2015年10月28日 下午4:37:31
* 程序的简单说明
*/
public class TestAdvisor implements PointcutAdvisor { public Advice getAdvice() {
return new TestAfterAdvisor() ;
} public boolean isPerInstance() {
return false;
} public Pointcut getPointcut() {
return new TestPointcut();
}
}

我使用的是包含了切点的通知器,所以在这里我们还要给出通知和切点,我写了两个简单的通知和切点。

 /**
* @author jing.ming
* @version 创建时间:2015年10月28日 下午4:39:30
* 程序的简单说明
*/
public class TestAfterAdvisor implements AfterReturningAdvice{ public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println("after " + target.getClass().getSimpleName() + "." + method.getName() + "()");
}
}

下面是切点,切点的描述是我们只增强test方法,不增强test2方法。

 package org.mj.springTest.aopTest;  

 import java.lang.reflect.Method;

 import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut; /**
* @author jing.ming
* @version 创建时间:2015年10月28日 下午4:42:07
* 程序的简单说明
*/
public class TestPointcut implements Pointcut { public ClassFilter getClassFilter() {
return ClassFilter.TRUE ;
} public MethodMatcher getMethodMatcher() {
return new MethodMatcher(){ public boolean isRuntime() {
return true;
} public boolean matches(Method method, Class<?> targetClass) {
if(method.getName().equals("test")){
return true ;
}
return false;
} public boolean matches(Method method, Class<?> targetClass, Object[] args) {
if(method.getName().equals("test")){
return true ;
}
return false;
} };
} }

好了,下面我们的准备工作都已经做好了。来看一下见证奇迹的时刻吧,我们使用IOC容器来帮我们完成增强,以下这段代码的运行需要cglib,测试代码如下:

 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext; /**
* @author jing.ming
* @version 创建时间:2015年10月28日 下午4:51:53
* 程序的简单说明
*/
public class TestAop { @SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(
"classpath:aopBean.xml");
TestTarget target = (TestTarget) applicationContext.getBean("testAop");
target.test();
System.out.println("------无敌分割线-----");
target.test2(); }
}

console输出:

target.test()
after TestTarget.test()
------无敌分割线-----
target.test2()

输入结果会发现,在target.test方法执行后,我们增强的afterReturningAdvice已经起作用了,但是我们将切点定义在了test方法,所以test2方法并没有被增强。

(转)spring AOP探索的更多相关文章

  1. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  2. 从源码入手,一文带你读懂Spring AOP面向切面编程

    之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代 ...

  3. Spring AOP事务管理(使用切面把事务管理起来)

    在<Spring Transaction 分析事务属性(事务的基本概念.配置)>基础上 http://blog.csdn.net/partner4java/article/details/ ...

  4. Spring AOP学习笔记01:AOP概述

    1. AOP概述 软件开发一直在寻求更加高效.更易维护甚至更易扩展的方式.为了提高开发效率,我们对开发使用的语言进行抽象,走过了从汇编时代到现在各种高级语言繁盛之时期:为了便于维护和扩展,我们对某些相 ...

  5. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  6. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  7. spring aop

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将 ...

  8. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  9. 基于Spring AOP的JDK动态代理和CGLIB代理

    一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的 ...

随机推荐

  1. Objective C NSString 编码成URL 特殊字符处理

    找了一下网上的教程都是使用类似以下代码,Xcode提示这个CoreFoundation不受ARC管理,所以折中的方式是添加__bridge. NSString *encodedValue = (__b ...

  2. Mac与Widow下编译与运行java文件引入多个外部jar包

    记录下,以后万一用得着呢 1.MAC环境下: 前提:在终端跳转到当前的源文件目录(cd xx), 并且配置好jdk,这里面不是重点 编译命令:注意连接用  :  号 javac -cp commons ...

  3. tensorflow wide deep 介绍

    https://blog.csdn.net/heyc861221/article/details/80131369 https://blog.csdn.net/heyc861221/article/d ...

  4. JS书籍推荐

    JS书籍推荐 一.总结 一句话总结: 二.JS进阶书籍 第一阶段:<JavaScript DOM编程艺术> 看这本书之前,请先确认您对Javascript有个基本的了解,应该知道if el ...

  5. 51nod-1574-排列转换

    1574 排列转换  题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 现在有两个长度为n的排列p和s.要求通过交换 ...

  6. 威佐夫博弈——hdu1527

    有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利. 直接说结论了,若两堆物品的初始值为(x,y),且x<y,则另z=y-x: 记w= ...

  7. 安装Linux环境

    虚拟机:虚拟机(Virtual Machine),在计算机科学中的体系结构里,是指一种特殊的软件,他可以在计算机平台和终端用户之间建立一种环境,而终端用户则是基于这个软件所建立的环境来操作软件.在计算 ...

  8. Java截取图片的一部分并保存为40*40的图片

    @Test public void testImag() { try { String path = "E:/flower2.jpg"; int x = 11, y = 20, c ...

  9. 跨域问题Java方式解决及Nginx方式解决【亲测可行】

    这两天和前端同事调试微信公众号项目,就遇到了跨域问题:网上相关博客也挺多的,但有很多细节没有点到,在此呢我也再次记录一下解决方式: (算是踩坑日记吧~ ~ ~)   !问题发现: 页面加载不出来,控制 ...

  10. 将VS2010环境设置为VC6.0样式(字体、前景色、背景色、Visual Assist X等)

    一.设置字体. 使用字体:Fixedsys Excelsior 3.01. 步骤1:下载字体. 步骤2:安装字体,控制面板->字体,复制下载的字体进去. 步骤3:打开VS2010,选择菜单:To ...