AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态植入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。然而殊途同归,实现AOP的技术特性却是相同的,分别为:

1 join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。

2 point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。

3 advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。

4 aspect(方面):point cut和advice结合起来就是aspect,它类似OOP中定义的一个类,但它代表的更多是对象间横向的关系。

5 introduce(引入):为对象引入附加的方法或属性,从而达到修改对象结构的目的。有的AOP工具又将其称为mixin。

上述的技术特性组成了基本的AOP技术,大多数AOP工具均实现了这些技术。它们也可以是研究AOP技术的基本术语。

举例:假设有在一个应用系统中,有一个共享的数据必须并发同时访问,首先,将这个数据封装在数据对象中,同时,将有多个访问类,专门用于在同一时刻访问这同一个数据对象。

*Demo实验:

a.创建两个接口类:TestServiceInter,TestServiceInter2,代码如下:

// TestServiceInter

public interface TestServiceInter {

public void sayHello();

}

// TestServiceInter2

public interface TestServiceInter2 {

public void sayBye();

}

b.创建一个类Test1Service实现以上接口

public class Test1Service implements TestServiceInter,TestServiceInter2 {

private String name;

public void setName(String name) {

this.name = name;

}

@Override

public void sayHello() {

System.out.println("hi"+name);

}

@Override

public void sayBye() {

System.out.println("bye"+name);

}

}

c.创建applicationContext.xml,配置必要的数据源和被代理的对象,代码如下:

<?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:context="http://www.springframework.org/schema/context"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理的对象 -->

<bean id="test1Service" class="com.ansibee.aop.Test1Service">

<property name="name" value="关羽"></property>

</bean>

</beans>

d.创建一个前置通知类MyMethodBeforeAdvice实现MethodBeforeAdvice接口,目的为了在执行sayHello()方法之前执行此段代码。代码如下:

public class MyMethodBeforeAdvice implements MethodBeforeAdvice{

/**

* method:被调用的方法名

* args:给method传递的参数

* target:目标对象

*/

@Override

public void before(Method method, Object[] args, Object target) throws Throwable {

// TODO Auto-generated method stub

System.out.println("*************");

System.out.println("日志记录:"+method.getName());

}

}

创建一个后置通知类MyAfterReturningAdvice实现AfterReturningAdvice接口,目的为了在执行sayBye()方法之后执行此段代码。代码如下:

public class MyAfterReturningAdvice implements AfterReturningAdvice {

@Override

public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {

// TODO Auto-generated method stub

System.out.println("关闭资源");

}

}

最后创建一个环绕通知类MyMethodInterceptor实现MethodInterceptor接口,环绕通知=前置通知+目标方法执行+后置通知,proceed ()方法就是用于启动目标方法执行的。代码如下:

public class MyMethodInterceptor implements MethodInterceptor {

@Override

public Object invoke(MethodInvocation arg0) throws Throwable {

// TODO Auto-generated method stub

System.out.println("调用方法前执行");

Object obj = arg0.proceed();

System.out.println("调用方法后执行");

return obj;

}

}

e.完成上述操作后去applicationContext.xml文件中进行相应的配置。代码如下:

</bean>

<!-- 配置前置通知 -->

<bean id="MyMethodBeforeAdvice" class="com.ansibee.aop.MyMethodBeforeAdvice"></bean>

<!-- 定义前置通知的接入点 -->

<bean id="MyMethodBeforeAdviceFilter" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">

<property name="advice" ref="MyMethodBeforeAdvice"></property>

<property name="mappedNames">

<list>

<value>sayHello</value>

</list>

</property>

</bean>

<!-- 配置后置通知 -->

<bean id="MyAfterReturningAdvice" class="com.ansibee.aop.MyAfterReturningAdvice"></bean> <!-- 配置环绕通知 -->

<bean id="MyMethodInterceptor" class="com.ansibee.aop.MyMethodInterceptor"></bean>

<!-- 配置代理对象 -->

<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">

<!-- 配置代理的接口集 -->

<property name="proxyInterfaces">

<list>

<value>com.ansibee.aop.TestServiceInter</value>

<value>com.ansibee.aop.TestServiceInter2</value>

</list>

</property>

<!-- 把通知织入到代理对象 -->

<property name="interceptorNames">

<!-- 相当于把前置通知和代理对象关联,可以把通知看作拦截器-->

list>

<!-- 织入前置通知,后置通知,环绕通知-->

<value>MyMethodBeforeAdviceFilter</value>

<!-- 使用自定义切入点控制前置使用 -->

<value>MyAfterReturningAdvice</value>

<value>MyMethodInterceptor</value>

</list>

</property>

<!-- 通知被代理对象,可以指定-->

<property name="target" ref="test1Service"></property>

</bean>

f.完成一系列配置后,可以进行测试了,测试类代码如下:

public class TestMain {

public static void main(String[] args) {

ApplicationContext ac = new ClassPathXmlApplicationContext("com/ansibee/aop/applicationContext.xml");

TestServiceInter ts = (TestServiceInter) ac.getBean("proxyFactoryBean");

ts.sayHello();

((TestServiceInter2)ts).sayBye();

}

}

然后run Java Application,运行结果如图

最新文章

  1. 简单生成svg文件
  2. python走起之第十一话
  3. python中logging
  4. HTML-002-弹出对话框
  5. Codeforces Round #121 (Div. 2)
  6. UVA 11916 Emoogle Grid 离散对数 大步小步算法
  7. Hibernate框架双向多对多关联映射关系
  8. 用powershell实现:“倩女幽魂姥姥”版《语音报警系统》
  9. SQL学习基础 =&gt; 创建表
  10. php file()函数
  11. mysql 开源~canal安装解析
  12. Generative Model 与 Discriminative Model
  13. 【Appium】Appium工作原理
  14. Java - 30 Java 网络编程
  15. VC CListCtrl 第一列列宽自适应
  16. 浅析HTTPS与SSL原理
  17. [51单片机] nRF24L01 无线模块 串口法命令 通过无线控制另一个的灯
  18. zend server mac 下配置
  19. CSS3背景总结
  20. Python基础:函数的介绍及应用

热门文章

  1. 关于java基础_数组的学习
  2. 项目初始化CSS公共样式
  3. tomcat源码之概述
  4. OpenGL渲染时的数据流动
  5. 最精美详尽的 HTTPS 原理图!
  6. Python-TypeError: object() takes no parameters
  7. java安全编码指南之:死锁dead lock
  8. 087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点
  9. 02 ArcPython的使用大纲
  10. Python实现的数据结构与算法之基本搜索详解