您的位置:首页 > 编程语言

面向切面编程(AOP)

2017-09-21 16:02 211 查看
谈到面向切面编程,就难免提到面向对象编程(OOP)

两者反映两种不同的设计思想,OOP将某一类实体及其属性和行为进行抽象和封装,通过类的实例化、对象之间的调用来组成完整程序。

而AOP中所谓的“切面”指的是业务处理过程中某个步骤或阶段,AOP是对这些步骤进行处理,以降低各个步骤间的耦合度。

简而言之,OOP是将现实存在的对象进行封装,例如对于“学生”这类对象,可以建立“Student”类,并将“上课”、“学习”等行为,以及“班级”、“学号”等属性封装在里面。

但这时还会有重复的情况,比如学生和教师查询学生成绩这个行为之后,都要记录一条日志,那么就在两个类中出现了同样的代码,即使将代码封装在一个类中,也需要分别调用这个类。这时就需要AOP了。AOP可以将记录日志的行为(不同类共有的代码)写在切片里,再在查询成绩的方法处设一个标记(切面),一运行到这里,就自动执行对应切片里的代码。

这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

知乎上的解释更简洁些:https://www.zhihu.com/question/24863332

AOP中的基本概念

1.Target object   

  AOP关注的业务部分。

2.Pointcut     

  AOP找到Target object后,准备在该对象的指定方法上执行Advice代码,而这个指定方法就是Pointcut。

3.Advice      

  在切点上真正执行的代码,写在一个java文件里。

4.join point    

  负责将Advice和Pointcut编织到一起(建立对应关系,使程序知Advice切入到哪里)

5.Aspect

  将pointcut、advice和joinpoint模块化,即共有功能的实现。

AOP需要的包:spring-aop-x.x.x.RELEASE.jar

       aspectjweaver-x.x.x.jar(待确认)

       

使用方法:

需要的文件:

  .xml配置文件

  Target object文件

  Advice文件

Target object文件(HelloService)内容如下:

package AOP_Demo;

public class HelloService
{
<!--一个普通方法-->
public void say()
{
System.out.println("eat");
}
}


Advice文件(MyAdv)内容如下:

package AOP_Demo;
import org.aopalliance.aop.Advice;

public class MyAdv implements Advice
{
<!--插入到pointcut的方法-->
public void beforeAdvice()
{
System.out.println("前置通知");
}
}


配置文件(app.xml)内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!--文件头需要增加一些内容-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 
<!--指定target object文件,根据情况改变-->
<bean id="target" class="AOP_Demo.HelloService"/>
<!--指定Advice文件,根据情况改变-->
<bean id="adv" class="AOP_Demo.MyAdv"/>
<!--Spring AOP的配置-->
<aop:config>
<!--Aspect-->
<aop:aspect ref="adv" id="asp">
<!--注意:可以使用通配符寻找pointcut,
一个*表示任意长度字符
两个.表示该包下的任意子包名
例:execution(* com.demo..*.*(..)
其中:第一个*表示当前方法对应的任意类型
后面的一串:表示demo包下任意子包下任意类的任意方法,
小括号中的..表示方法中的任意个数、类型的参数
-->
<!--定义pointcut,可见指向了Target object中的.say()方法-->
<aop:pointcut expression="execution(void AOP_Demo.HelloService.say())" id="pc"/>
<!--定义织入的方式(before)、方法(beforeAdvice)和pointcut(pc),即“在运行pointcut指定的方法之前执行Advice中的beforeAdvice方法”
Advice文件位置是在<aop:aspect>中通过ref定义的-->
<aop:before method="beforeAdvice" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>

</beans>


下面写一个带主方法的文件,来运行一下:

package AOP_Demo;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest
{
public static void main(String args[])
{
ApplicationContext c;
c = new ClassPathXmlApplicationContext("app.xml");
HelloService h = (HelloService) c.getBean("target");
h.say();
}
}


结果如下:

前置通知
eat


可见,执行Target object的.say()方法之前,自动执行了Advice中的指定方法。

(待完善)

(萌新一枚,难免有错误或疏漏,欢迎指正)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  aop spring