AOPAOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。 AOP核心概念1、横切关注点对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点2、切面(aspect)类是对物体特征的抽象,切面就是对横切关注点的抽象3、连接点(joinpoint)被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器4、切入点(pointcut)对连接点进行拦截的定义5、通知(advice)所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类6、目标对象代理的目标对象7、织入(weave)将切面应用到目标对象并导致代理对象创建的过程8、引入(introduction)在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段 Spring对AOP的支持Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIBAOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:1、定义普通业务组件2、定义切入点,一个切入点可能横切多个业务组件3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。下面给出一个Spring AOP的.xml文件模板,名字叫做aop.xml,之后的内容都在aop.xml上进行扩展:<?xml version="1.0" encoding="UTF-8"?>

基于Spring的AOP简单实现注意一下,在讲解之前,说明一点:使用Spring AOP,要成功运行起代码,只用Spring提供给开发者的jar包是不够的,请额外上网下载两个jar包:1、aopalliance.jar2、aspectjweaver.jar开始讲解用Spring AOP的XML实现方式,先定义一个接口:public interface HelloWorld
{
void printHelloWorld();
void doPrint();
}定义两个接口实现类:public class HelloWorldImpl1 implements HelloWorld
{
public void printHelloWorld()
{
System.out.println(“Enter HelloWorldImpl1.printHelloWorld()”);
}

public void doPrint()
{System.out.println("Enter HelloWorldImpl1.doPrint()");return ;
}

}public class HelloWorldImpl2 implements HelloWorld
{
public void printHelloWorld()
{
System.out.println(“Enter HelloWorldImpl2.printHelloWorld()”);
}

public void doPrint()
{System.out.println("Enter HelloWorldImpl2.doPrint()");return ;
}

}横切关注点,这里是打印时间:public class TimeHandler
{
public void printTime()
{
System.out.println("CurrentTime = " + System.currentTimeMillis());
}
}有这三个类就可以实现一个简单的Spring AOP了,看一下aop.xml的配置:<?xml version="1.0" encoding="UTF-8"?>

    <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /><bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /><bean id="timeHandler" class="com.xrq.aop.TimeHandler" /><aop:config><aop:aspect id="time" ref="timeHandler"><aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" /><aop:before method="printTime" pointcut-ref="addAllMethod" /><aop:after method="printTime" pointcut-ref="addAllMethod" /></aop:aspect></aop:config>

写一个main函数调用一下:public static void main(String[] args)
{
ApplicationContext ctx =
new ClassPathXmlApplicationContext(“aop.xml”);

HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1");
HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2");
hw1.printHelloWorld();
System.out.println();
hw1.doPrint();System.out.println();
hw2.printHelloWorld();
System.out.println();
hw2.doPrint();

}运行结果为:CurrentTime = 1446129611993
Enter HelloWorldImpl1.printHelloWorld()
CurrentTime = 1446129611993

CurrentTime = 1446129611994
Enter HelloWorldImpl1.doPrint()
CurrentTime = 1446129611994

CurrentTime = 1446129611994
Enter HelloWorldImpl2.printHelloWorld()
CurrentTime = 1446129611994

CurrentTime = 1446129611994
Enter HelloWorldImpl2.doPrint()
CurrentTime = 1446129611994看到给HelloWorld接口的两个实现类的所有方法都加上了代理,代理内容就是打印时间 基于Spring的AOP使用其他细节1、增加一个横切关注点,打印日志,Java类为:public class LogHandler
{
public void LogBefore()
{
System.out.println(“Log before method”);
}

public void LogAfter()
{System.out.println("Log after method");
}

}aop.xml配置为:<?xml version="1.0" encoding="UTF-8"?>

    <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /><bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /><bean id="timeHandler" class="com.xrq.aop.TimeHandler" /><bean id="logHandler" class="com.xrq.aop.LogHandler" /><aop:config><aop:aspect id="time" ref="timeHandler" order="1"><aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.*(..))" /><aop:before method="printTime" pointcut-ref="addTime" /><aop:after method="printTime" pointcut-ref="addTime" /></aop:aspect><aop:aspect id="log" ref="logHandler" order="2"><aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.*(..))" /><aop:before method="LogBefore" pointcut-ref="printLog" /><aop:after method="LogAfter" pointcut-ref="printLog" /></aop:aspect></aop:config>

测试类不变,打印结果为:CurrentTime = 1446130273734
Log before method
Enter HelloWorldImpl1.printHelloWorld()
Log after method
CurrentTime = 1446130273735

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl1.doPrint()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl2.printHelloWorld()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273737
Log before method
Enter HelloWorldImpl2.doPrint()
Log after method
CurrentTime = 1446130273737要想让logHandler在timeHandler前使用有两个办法:(1)aspect里面有一个order属性,order属性的数字就是横切关注点的顺序(2)把logHandler定义在timeHandler前面,Spring默认以aspect的定义顺序作为织入顺序2、我只想织入接口中的某些方法修改一下pointcut的expression就好了:<?xml version="1.0" encoding="UTF-8"?>

    <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" /><bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" /><bean id="timeHandler" class="com.xrq.aop.TimeHandler" /><bean id="logHandler" class="com.xrq.aop.LogHandler" /><aop:config><aop:aspect id="time" ref="timeHandler" order="1"><aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.print*(..))" /><aop:before method="printTime" pointcut-ref="addTime" /><aop:after method="printTime" pointcut-ref="addTime" /></aop:aspect><aop:aspect id="log" ref="logHandler" order="2"><aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.do*(..))" /><aop:before method="LogBefore" pointcut-ref="printLog" /><aop:after method="LogAfter" pointcut-ref="printLog" /></aop:aspect></aop:config>

表示timeHandler只会织入HelloWorld接口print开头的方法,logHandler只会织入HelloWorld接口do开头的方法3、强制使用CGLIB生成代理前面说过Spring使用动态代理或是CGLIB生成代理是有规则的,高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是aop:config里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用。

java 中什么是aop相关推荐

  1. java中ioc和aop是什么?【杭州多测师】【杭州多测师_王sir】

    一.什么是IOC? 1.IoC (Inversion of control )就是控制反转/反转控制.它是一种思想不是一个技术实现.主要就是用来解决创建和管理对象的 2.就是不需要通过new 关键字来 ...

  2. 什么是 Java 中的 AOP(面向切面编程)?如何使用它来实现横切关注点?

    AOP(Aspect-oriented programming,面向切面编程),是一种编程思想和技术,旨在将横切关注点和主业务逻辑分离,使得系统更容易扩展和维护.在 Java 中,AOP 主要通过代理 ...

  3. [转]JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分

    首先这是现在最基本的分层方式,结合了SSH架构.modle层就是对应的数据库表的实体类.Dao层是使用了Hibernate连接数据库.操作数据库(增删改查).Service层:引用对应的Dao数据库操 ...

  4. java中注解的使用_java中注解的使用

    使用过ssh框架的人一定也使用过注解,尤其是在spring框架中,注解可谓是spring容器和AOP编程的重要环节.注解就是用于修饰类.全局变量.方法.参数或局部变量的接口,java中规定,注解的使用 ...

  5. 了解Java中的内存泄漏

    来源:SpringForAll社区 1. 简介 Java的核心优势之一是在内置垃圾收集器(简称GC)的帮助下实现自动内存管理.GC隐含地负责分配和释放内存,因此能够处理大多数内存泄漏问题. 虽然GC有 ...

  6. Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP

    Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP xBird 原创  (参与分:36,专家分:90)   发表:2004-9-3 上午9:37   版本:1.0   阅读:160 ...

  7. 吃透Java中的动态代理

    动态代理在Java中是很重要的一部分,在很多框架中都会用到,如Spring中的AOP.Hadoop中的RPC等.为此在这把我对Java中的动态代理的理解分享给大家,同时写了一个模拟AOP编程的实例.( ...

  8. java中动态代理实现机制

    v前言: 代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关 ...

  9. 详解 Java 中的三种代理模式

    代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用 ...

最新文章

  1. adb server无法启动方法,结束占用端口的进程
  2. java手机杀毒_Android项目实战_手机安全卫士splash界面
  3. 设计模式—责任链模式
  4. 44. 源代码解读-RocketMQ-架构
  5. 关于内存对齐问题的一些资料整理
  6. jsp内置对象的提交方式
  7. CSDN博客搬家到WordPress
  8. 看看MySQL几种主流备份方案的优缺点
  9. ios模拟器安装app
  10. ubuntu14.04下deb文件安装mysql数据库
  11. 支付宝(Alipay)支付,超详细使用教程讲解!
  12. 概率论复习笔记(一)随机事件及其概率
  13. 深度学习之前馈神经网络(前向传播和误差反向传播)
  14. Python 分别获取日期中的年月日时分秒
  15. 在MOSS中开发和部署Infopath
  16. Java——【习题】java泛型练习题
  17. Visual Studio(VS) 编程推荐字体和主题设置
  18. Vue之Vue的初体验
  19. ract-native常用命令
  20. the 95th-percentile ,50th,99th等

热门文章

  1. 硬盘升级的理由 和老硬盘的处理
  2. 比以往来得更猛烈的免费WiFi
  3. vb6里解析json数据
  4. LeetCode 349. 两个数组的交集【哈希表】
  5. 在树莓派上搭建MQTT服务器
  6. 【练习】2020校招4399游戏开发岗笔试编程题 C++(4)
  7. 【图像分割】基于均值聚类+OUST+区域生长法实现MRI图像分割附matlab代码
  8. 为什么牛逼互联网公司都在开曼群岛注册?
  9. QSPI(QUAD SPI)基本信息
  10. HC32F460 QSPI底层驱动(W25Q128)