AOP,即Aspect Oriented Programming,面向切面编程。通过预编译和运行期动态代理实现程序功能的统一维护的一种技术。跟OOP不一样,OOP中的有很重要的继承,跟继承中各个类存在纵向关联不同,AOP是横向关联。AOP主要是对业务逻辑各部分进行隔离,降低程序之间的耦合度,提高代码复用性,提高开发效率以及可维护性。。
举个简单例子:
有好几个类中(A.class,B.class==)都需要加一些公共代码,比如常见的日志打印。需要在某个方法执行前或者执行后打印日志,说得不恰当一点,将两个class横向摆在一起,相当于两片面包,我们要做的操作就是横向切开面包,往中间放上果酱,然后再拼成新面包,这个时候就可以用到面向切面编程了。当然不止这些场景,常见的还有事务管理,缓存等等。
AOP常见概念
1-通知(Advice):通知定义了切面是什么以及何时使用.描述了切面要完成的工作和何时需要执行这个工作.
2-连接点(Joinpoint):程序能够应用通知的一个"时机",这些"时机"就是连接点,例如方法被调用时,异常被抛出时.
3-切入点(Pointcut):通知定义了切面要发生的"故事"和时间,那么切入点就定义了"故事"发生的地点,例如某个
类或方法的名称,Spring中允许我们方便的用正则表达式来指定
4-切面(Aspect):通知和切入点共同组成了切面,时间,地点和要发生的"故事"
5-引入(Introduction):引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)
6-目标(Target):即被通知的对象,如果没有Aop,那么它的逻辑将要交叉别的事务逻辑,有了Aop之后它可以
只关注自己要做的事(Aop让他做爱做的事)
7-代理(Proxy):应用通知的对象,详细内容参见设计模式里面的代理模式
8-织入(Weaving):把切面应用到目标对象来创建新的代理对象的过程。
实现AOP的两种代理:JDK自带的以及Cglib动态代理。
下面举例说明:
先定义配置文件applicationContext:(此示例来自于《Spring In Action》)
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<bean id="performer" class="com.sgx.aop.Performer">
<property name="name" value="jack"/>
</bean>
<bean id="audience" class="com.sgx.aop.Audience"/>
<aop:config>
<aop:aspect ref="audience">
<aop:before method="takeseat" pointcut="execution(* *.perform(..))"/>
<aop:before method="turnoffphone" pointcut="execution(* *.perform(..))"/>
<aop:after-returning method="applaud" pointcut="execution(* *.perform(..))"/>
<aop:after-throwing method="unhappy" pointcut="execution(* *.perform(..))"/>
</aop:aspect>
</aop:config>
</beans>
定义接口perform:
package com.sgx.aop;
public interface Perform {
void perform();
}
定义表演者performer及听众audience类:
package com.sgx.aop;
public class Performer implements Perform{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void perform(){
System.out.println(this.name+"Sing a Song!");
}
}
package com.sgx.aop;
public class Audience {
public void takeseat(){
System.out.println("audience take seat and sit down");
}
public void turnoffphone(){
System.out.println("turn off your phones");
}
public void applaud(){
System.out.println("Clap Clap Clap....");
}
public void unhappy(){
System.out.println("audiences are unhappy");
}
}
然后进行测试:
package com.sgx.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class TestAop {
public static void main(String[] args){
ApplicationContext ctx=new FileSystemXmlApplicationContext("src/applicationContext.xml");
Perform p=(Perform)ctx.getBean("performer");
p.perform();
}
}
测试结果如下:
2017-10-29 0:49:05 org.springframework.context.support.FileSystemXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@b23b25c: startup date [Sun Oct 29 00:49:05 CST 2017]; root of context hierarchy
2017-10-29 0:49:05 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [E:\Workspace\BankTest\SpringTest\src\applicationContext.xml]
audience take seat and sit down
turn off your phones
jackSing a Song!
Clap Clap Clap....