您的位置:首页 > 运维架构

简单理解AOP

2017-08-16 11:35 141 查看

AOP的概念:中文翻译为面向切面编程。

个人理解:在正常的多条业务中,如果有一项其他任务需要运用到所有这些业务中去,且和这些业务的本身没有关系。那么这个其他任务就成为切面,切入了这些多条业务中。

很抽象,还是不理解。画个图。



假设一个停车场,有许多辆车要开出停车场,对于车来说,它要做的只是开出停车场,而停车场要做的就是升起杆子供车通过,并在车子通过后降下杆子,把各个牌子的车子本身开出停车场的行为看成是各自独立的业务。看似简单的功能,如果对于一辆车的开出停车场功能,我可以写升起杆子,开出停车场,降落杆子三件事。对于奔驰车通过,我需要写这三件事,对于宝马车通过,我需要写三件事。想想就很麻烦,而且车子是车子的事,停车场是停车场的事,这怎么能归为一谈呢,并不符合单一事务原则的思想啊。

那么我们需要一个切面,这个切面就是停车场做的事,它一刀切下所有车子开出停车场的事件,让每辆车开出停车场,停车场都可以升起降下杆子。这样多好。

AOP术语:

1.通知(Advice):

通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。

2.连接点(Joinpoint):

程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。
3.切入点(Pointcut)

通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,spring中允许我们方便

的用正则表达式来指定

4.切面(Aspect)

通知和切入点共同组成了切面:时间、地点和要发生的“故事”

5.引入(Introduction)

引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)

6.目标(Target)

即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做

的事)

7.代理(proxy)

应用通知的对象,详细内容参见设计模式里面的代理模式

8.织入(Weaving)

把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:

(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器

(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码

(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

看这么多没用,先用起来再说!先看最新的Spring配置中AOP如何使用

Spring2.x版本之后需要引入这个jar包

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>

目标:新建汽车接口,并实例各种汽车实现汽车接口。然后在执行汽车run方法前后,停车场会执行杆子升起和降下的方法,实现切面效果。

新建汽车接口Car,汽车接口只有一个run方法:

public interface Car{

/**
* 车子开
*/
void run();
}


BMW宝马实现Car接口,并且实现run方法:

public class BMW implements Car{

public void run(){
System.out.println("宝马开出停车场");
}

}


福特实现Car接口,并且实现run方法:

public class Ford implements Car{

public void run(){
System.out.println("福特开出停车场");
}

}


还需要一个停车场类来实现输出杆子的升起和降下:

public class Parking{

public void beforeCarRun(){
System.out.println("停车场杆子升起");
}

public void afterCarRun(){
System.out.println("停车场杆子降下");
}
}


最后是AOP配置:

<!-- 通知 -->
<bean id="parking" class="com.aop.Parking">
</bean>
<!-- 目标对象 -->
<bean id="bmw" class="com.aop.BMW">
</bean>
<bean id="ford" class="com.aop.Ford">
</bean>

<aop:config>
<aop:aspect id="parkingAspect" ref="parking">
<!-- 织入  -->
<!-- pointcut 是切点,对应哪个方法 -->
<aop:before method="beforeCarRun" pointcut="execution(* *.run(..))"/>
<aop:after method="afterCarRun" pointcut="execution(* *.run(..))"/>
</aop:aspect>
</aop:config>


测试:

public static void main(String[] args){
ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car1 = (Car)appCtx.getBean("bmw");
Car car2 = (Car)appCtx.getBean("ford");
car1.run();
car2.run();
}


执行结果:

停车场杆子升起

宝马开出停车场

停车场杆子降下

停车场杆子升起

福特开出停车场

停车场杆子降下

可以看到,宝马和福特开出停车场,停车场均执行了杆子升起和降下方法,且和车子本身独立开来了。

ok。实现了效果。接下去,就需要由浅入深来理解SpringAOP的实现机制了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: