AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即切面。所谓“切面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向切面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“切面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,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。
6、AOP代理(AOP Proxy):AOP框架创建的对象,这个对象通常可以作为目标对象的替代品,而AOP代理提供比目标对象更加强大的功能。真实的情形是,当应用调用AOP代理的方法时,AOP代理会在自己的方法中回调目标对象的方法,从而完成应用的调用。关于AOP代理的典型例子就是Spring中的事务代理Bean。通常,目标Bean的方法不是事务性的,而AOP代理包含目标Bean的全部方法,而且这 些方法经过加强变成了事务性方法。简单地说,目标对象是蓝本,AOP代理是目标对象的加强,在目标对象的基础上,增加属性和方法,提供更强大的功能。
目标对象包含一系列切入点。切入点可以触发处理连接点集合。用户可以自己定义切入点,如使用正则表达式。AOP代理包装目标对象,在切入点处加入处理。在切入点加入的处理,使得目标对象的方法功能更强。Spring 默认使用JDK动态代理实现AOP代理,主要用于代理接口。也可以使用CGLIB代理。实现类的代理,而不是接口。如果业务对象没有实现接口,默认使用 CGLIB代理。但面向接口编程是良好的习惯,尽量不要面向具体类编程。因此,业务对象通常应实现一个或多个接口。
7、目标对象(Target Object):包含一个连接点的对象,也被称为代理对象。
8、 前置通知(Before advice):在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext中在aop:aspect里面使用aop:before元素进行声明。
9、后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext中在aop:aspect里面使用aop:after元素进行声明。
10、返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext中在aop:aspect里面使用元素进行声明。
11、环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。ApplicationContext中在aop:aspect里面使用aop:around元素进行声明。

12、抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。 ApplicationContext中在aop:aspect里面使用aop:after-throwing元素进行声明。

packages:

    <dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

代码:

package com.qhong;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
Person babyPerson=(BabyPerson)context.getBean("babyPerson");
babyPerson.eatBreakfast();
babyPerson.eatLunch();
babyPerson.eatSupper();
}
} interface Person {
public void eatBreakfast();
public void eatLunch();
public void eatSupper();
} class BabyPerson implements Person{ @Override
public void eatBreakfast() {
System.out.println("小Baby正在吃早餐");
} @Override
public void eatLunch() {
System.out.println("小Baby正在吃午餐");
} @Override
public void eatSupper() {
System.out.println("小Baby正在吃晚餐");
}
} class AdviceMethod {
public void beforeEat(){
System.out.println("-------------------吃饭之前先洗小手!--------------------");
}
public void afterEat(){
System.out.println("-------------------午饭吃完要睡午觉!--------------------");
}
public Object aroundEat(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("-------------------吃晚饭前先玩一玩!-------------------");
Object retVal = pjp.proceed();
System.out.println("-------------------晚饭吃完后要得睡觉了!-------------------");
return retVal;
}
}

beans.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="babyPerson" class="com.qhong.BabyPerson"/><!-- 被增强的bean -->
<bean id="adviceAspect" class="com.qhong.AdviceMethod"/><!-- 增强方法的bean --> <aop:config proxy-target-class="true">
<!-- 定义切点 -->
<aop:pointcut id="pointcut" expression="execution(* com.qhong.BabyPerson.*(..))"/>
<!-- 定义切面 -->
<aop:aspect ref="adviceAspect">
<!-- 定义前置增强方法 -->
<aop:before method="beforeEat" pointcut-ref="pointcut" />
<!--定义后置增加,使用匿名切点 -->
<aop:after method="afterEat" pointcut="execution(* com.qhong.BabyPerson.eatLunch(..))"/>
<!--定义后置增加,使用匿名切点 -->
<aop:around method="aroundEat" pointcut="execution(* com.qhong.BabyPerson.eatSupper(..))"/>
</aop:aspect>
</aop:config>
</beans>

Result:

-------------------吃饭之前先洗小手!--------------------
小Baby正在吃早餐
-------------------吃饭之前先洗小手!--------------------
小Baby正在吃午餐
-------------------午饭吃完要睡午觉!--------------------
-------------------吃饭之前先洗小手!--------------------
-------------------吃晚饭前先玩一玩!-------------------
小Baby正在吃晚餐
-------------------晚饭吃完后要得睡觉了!-------------------

Demo2:

package com.qhong;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component; public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Greeting greeting = (Greeting) context.getBean("greetingImpl");
greeting.sayHello("Jack");
}
} interface Greeting {
void sayHello(String name);
} @Component
class GreetingImpl implements Greeting {
@Override
public void sayHello(String name) {
System.out.println("Hello! " + name);
}
} class GreetingAspect {
public Object around(ProceedingJoinPoint pjp) throws Throwable {
before();
Object result = pjp.proceed();
after();
return result;
} private void before() {
System.out.println("Before");
} private void after() {
System.out.println("After");
}
}

spring.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:aop="http://www.springframework.org/schema/aop"
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"> <bean id="greetingImpl" class="com.qhong.GreetingImpl"/> <bean id="greetingAspect" class="com.qhong.GreetingAspect"/> <aop:config>
<aop:aspect ref="greetingAspect">
<aop:around method="around" pointcut="execution(* com.qhong.GreetingImpl.*(..))"/>
</aop:aspect>
</aop:config> </beans>

Result:

Before
Hello! Jack
After

http://www.kancloud.cn/evankaka/springlearning/119669

https://my.oschina.net/huangyong/blog/161338

http://git.oschina.net/lujianing/aop_demo

AOP Schema配置的更多相关文章

  1. 基于Schema配置切面

        使用基于Schema的切面定义后,切点.增强类型的注解信息从切面类中剥离出来,原来的切面类也就蜕变为真正意义上的POJO了. 1.一个简单切面的配置 基于Schema配置的切面示例: < ...

  2. Spring学习4-面向切面(AOP)之schema配置方式

    一.通过Scheme配置实现AOP步骤(Spring AOP环境的环境与上篇博文 Spring接口方式相同)    步骤一.编写业务类: public class AspectBusiness {   ...

  3. 基于注解的Spring AOP的配置和使用

    摘要: 基于注解的Spring AOP的配置和使用 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不 ...

  4. 基于注解的Spring AOP的配置和使用--转载

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  5. Spring AOP Schema aop:config、tx:advice

    Spring AOP Schema  aop:config.tx:advice 一.      利用aop:config标签实现AOP 首先看个例子,如下 接口代码: package com.lei. ...

  6. Spring学习(20)--- Schema-based AOP(基于配置的AOP实现) -- 配置切入点pointcut

    pointcut(切断点)表达式: execution(public * *(..)) execution(* set*(..)) execution(* com.xyz.service.Accoun ...

  7. Spring学习(19)--- Schema-based AOP(基于配置的AOP实现) --- 配置切面aspect

    Spring所有的切面和通知器都必须放在一个<aop:config>内(可以配置包含多个<aop:config>元素),每个<aop:config>包含pointc ...

  8. springAop:Aop(Xml)配置,Aop注解配置,spring_Aop综合案例,Aop底层原理分析

    知识点梳理 课堂讲义 0)回顾Spring体系结构 Spring的两个核心:IoC和AOP 1)AOP简介 1.1)OOP开发思路 OOP规定程序开发以类为模型,一切围绕对象进行,OOP中完成某个任务 ...

  9. 基于XML配置的spring aop增强配置和使用

    在我的另一篇文章中(http://www.cnblogs.com/anivia/p/5687346.html),通过一个例子介绍了基于注解配置spring增强的方式,那么这篇文章,只是简单的说明,如何 ...

随机推荐

  1. Java多线程详解(三)

    1)死锁 两个线程相互等待对方释放同步监视器时会出现死锁的现象,这时所有的线程都处于阻塞状态,程序无法继续向下执行. 如下就是会出现死锁的程序. 首先flag = 1,线程d1开始执行,锁住对象o1, ...

  2. weblogic新漏洞学习cve-2017-10271

    一.原理: 很明显啦,readobject又出来背锅了,一个XML的反序列化漏洞导致的命令执行. 具体原理我看不懂java代码的我也只能学习别人的分析.给出一篇参考文章,写的非常详细: 漏洞原理 二. ...

  3. Minix2.0操作系统kernel文件分析

    详细分析  MINIX消息机制的核心: mpx386.s start.c proc.c 保护模式分析: src/kernel/exception.c src/kernel/protect.c src/ ...

  4. 【BZOJ3156】防御准备 斜率优化

    [BZOJ3156]防御准备 Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小 ...

  5. Mac/Xcode - 开发技巧快捷键

    Xcode是iPhone和iPad开发者用来编码或者开发iOS app的IDE.Xcode有很多小巧但很有用的功能,很多时候我们可能没有注意到它们,也或者我们没有在合适的水平使用这些功能简化我们的iO ...

  6. 网络流SAP+gap+弧优化算法

    poj1273 Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 54962   Accept ...

  7. pta习题集5-16 朋友圈

    某学校有N个学生,形成M个俱乐部.每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈.一个学生可以同时属于若干个不同的俱乐部.根据"我的朋友的朋友也是我的朋友"这个推论可以得 ...

  8. ZOJ 3202 Second-price Auction

    Second-price Auction Time Limit: 1 Second      Memory Limit: 32768 KB Do you know second-price aucti ...

  9. poj1191 棋盘分割【区间DP】【记忆化搜索】

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16263   Accepted: 5812 Description ...

  10. In ZeroDB, the client is responsible for the database logic. Data encryption, decryption, and compression also happen client side. Therefore, the server never has any knowledge about the data, its str

    zerodb/index.rst at master · zerodb/zerodb https://github.com/zerodb/zerodb/blob/master/docs/source/ ...