介绍

在理想的面向对象系统中,我们希望将每个对象设计为执行一项特定任务。 但是,除了执行其主要任务外,对象还执行被动任务,例如日志记录,事务,安全性,缓存等。这些被动活动是必需的,但不是业务逻辑的一部分,被称为“ 跨切问题 ”。

(横切关注点==系统中常用的功能)

横切关注点与业务逻辑分开可能是编写精心设计的解耦代码的重要一步。 让我们思考一下解决交叉切割问题的方法

遗产

继承立即在脑海中弹出,我们可以继承通用功能并在对象中使用它。 但是继承通用功能需要我们设计一个基类。 如果我们在多个地方重用该类,那么以后修改类可能会很困难。

继承==以后很难修改(非弹性代码)

代表团

委派是处理交叉切割问题的更好方法。 记住组成要重于继承,(授权和组成要共同关注)。 但是,那么我们将不得不在许多地方进行调用以委托对象,从而使其变得繁琐。

委派==繁琐

面向方面的编程

这是否意味着我们要喝汤了。 相反,这给我们提供了第三种也是最好的方法,即面向方面的编程。 AOP避免了继承的脆弱性和委派的繁琐性。 AOP在相互交叉的关注点领域大放异彩

什么是AOP?

AOP允许我们将横切关注点模块化到称为Aspects的特殊对象中,从而创建更清晰和分离的代码。 有了适当的方面,对象就不必担心执行被动横切问题,因为AOP会处理所有这些问题。

与AOP有关的术语

像任何成功的技术一样,AOP也带有自己的术语和术语集。 让我们先看一下那些,然后再进行更深入的了解AOP的工作。

  1. 关注 –这些是基于其功能模块化的系统的一部分。 有两种类型的关注点。 1.核心关注点2.跨领域关注点。 核心关注点与系统的业务逻辑相关,即系统执行的主动任务,例如生成工资单,获取员工记录,进行银行转账等。跨部门关注点是执行主动任务(例如日志记录,缓存)所需的被动任务等等
  2. 连接点–连接点是执行流程中的一点,其中发生了一些动作,并且有可能应用Aspect(跨领域关注点)。 连接点可以是调用方法,引发异常或对象状态改变。
  3. 建议 – AOP中的每个方面都有其目的,即它必须完成的工作。 该作业必须在连接点处应用。 方面的工作或目的称为建议。 除了定义方面的工作之外,建议还定义方面执行工作的时间。 应该在核心任务完成执行之前或之后应用作业,还是在两者之前和之后应用作业。
  4. 切入点 –系统中可以有许多连接点,但是并非所有方面都由Aspect建议。 Aspect从Pointcut获得帮助,以选择要在其中编织建议的Joinpoint。
  5. 方面 –建议和切入点定义了方面。 正如我们看到的,建议定义了方面的工作以及何时执行。 虽然Pointcut定义了方面编织建议的位置。 因此,工作的内容,时间和地点定义了方面。
  6. 目标 –目标是被建议的对象。 (核心关注)。 在AOP的帮助下,该对象可以自由地执行其主要任务,而不必担心交叉问题。
  7. 代理 –将建议应用于目标对象时,将创建一个代理对象。 AOP容器创建并管理对象的生命周期,程序员无需担心它们。
  8. 编织 –编织是将Advice或Aspect应用于目标对象以创建代理对象的过程。 编织可以在编译时或类加载时或在运行时完成。 通常,Spring AOP在运行时将方面编织到目标对象中。

那是要消化的一长串术语。 在继续之前,请花点时间了解它们。

咨询类型

沉迷于示例之前的最后一篇文章是学习建议的类型。 主要有4种建议。

  1. 建议之前 –在Joinpoint开始执行之前应用建议之前。 通过实现org.springframework.aop.MethodBeforeAdvice接口来创建BeforeAdvice。 要实现的方法是公共无效(方法m,对象args [],对象目标)抛出Throwable
  2. 返回建议之后–在Joinpoint完成执行之后应用建议之后。 AfterReturningAdvice是通过实现org.springframework.aop.AfterReturningAdvice接口创建的。 ThingableReturning(Method m,Object args [],Object target)抛出后 ,要实现的方法是公共无效
  3. 引发建议 –当Joinpoint在执行过程中引发异常时,将应用引发建议。
  4. 围绕建议 –此建议围绕Joinpoint执行,并在Joinpoint执行之前和之后执行。 这甚至可以用来控制Joinpoint的调用。

我们将尝试在SpringAOP的帮助下开发一个简单的缓存。 缓存具有三个主要的核心问题。

核心关注点

  1. 将对象保存在缓存中。
  2. 从缓存返回对象。
  3. 从缓存中删除对象。

现在,除了这些核心问题之外,缓存框架还有其他被动任务。 这些被动任务构成了交叉问题。

横切关注点

  1. 达到其大小限制时重新调整缓存大小。 (LRU)实施。
  2. 锁定对象以防止在读取对象时将其删除。
  3. 锁定高速缓存以防止在调整大小时阻止和读取/写入/删除高速缓存。

编码所有这些横切关注点可能是耗时且乏味的,因此让我们简化示例,当缓存已满时,我们将仅实现调整大小逻辑。 因此,在完成示例之后,我们将拥有一个可以放置,获取和删除对象的缓存。 例如,缓存的最大大小已设置为10。 一旦高速缓存存储了10个对象,则对高速缓存的任何添加都将导致通过删除第一个对象来删除(重新调整大小)高速缓存。 调整大小的操作由使用Spring AOP创建的Aspect控制。 这是示例中要遵循的步骤

可以从SVN此处下载示例代码: https : //www.assembla.com/code/weblog4j/subversion/nodes/31/SpringDemos/trunk

  1. 依赖关系 – AOP是spring的核心功能,因此要使Spring AOP正常运行,我们需要的是核心spring jar,因此在您的POM中添加以下依赖关系。

    <dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency>
  2. 核心缓存对象。
    package com.aranin.spring.aop;import java.util.Date;
    import java.util.LinkedHashMap;
    import java.util.Map;public class MyCache {private LinkedHashMap<String, Object> cacheMap = new  LinkedHashMap<String, Object>();private LinkedHashMap<String, Date> timeStampMap = new  LinkedHashMap<String, Date>();/*** defines the max size of hashmap*/private long maxsize = 10;  //should come from properties file or some configuration/*** how long the object should be stored before it is evicted from cache*/private long objectLifeTime = 10000;private boolean lock = false;public LinkedHashMap<String, Object> getCacheMap() {return cacheMap;}public void setCacheMap(LinkedHashMap<String, Object> cacheMap) {this.cacheMap = cacheMap;}public LinkedHashMap<String, Date> getTimeStampMap() {return timeStampMap;}public void setTimeStampMap(LinkedHashMap<String, Date> timeStampMap) {this.timeStampMap = timeStampMap;}public long getMaxsize() {return maxsize;}public void setMaxsize(long maxsize) {this.maxsize = maxsize;}public long getObjectLifeTime() {return objectLifeTime;}public void setObjectLifeTime(long objectLifeTime) {this.objectLifeTime = objectLifeTime;}public boolean isLock() {return lock;}public void setLock(boolean lock) {this.lock = lock;}/*** This method is used to retrive the object from cache* @param key* @return*/public Object get(String key){return this.getCacheMap().get(key);}/*** this method is used for putting an object in cache* @param key* @param object*/public void put(String key, Object object){//get the curr dateDate date = new Date(System.currentTimeMillis());//set object in cacheMapthis.getCacheMap().put(key,object);//put timestamp in cachethis.getTimeStampMap().put(key, date);}public void delete(String key){this.getCacheMap().remove(key);this.getTimeStampMap().remove(key);}public void clearAll(){this.setCacheMap(new  LinkedHashMap<String, Object>());this.setTimeStampMap(new  LinkedHashMap<String, Date>());}/*** remove last 2 entries* not worried about object life time* this is just an example*/public void resize(){System.out.println("inside resize");long size = this.getCacheMap().size();System.out.println("size + " + size);if(size == this.getMaxsize()){System.out.println("max size has reached");Map.Entry<String, Date> firstEntry = this.getTimeStampMap().entrySet().iterator().next();System.out.println("removing : " + firstEntry.getKey() + " value : " + firstEntry.getValue());this.timeStampMap.remove(firstEntry.getKey());Map.Entry<String, Object> firstCEntry = this.getCacheMap().entrySet().iterator().next();System.out.println("removing : " + firstCEntry.getKey() + " value : " + firstCEntry.getValue());this.cacheMap.remove(firstCEntry.getKey());}System.out.println("leaving resize with size : " + this.getCacheMap().size());}
    }

    这个课没什么好说的。 有两个LinkedHashMaps,一个用于存储对象,另一个用于存储将对象推入缓存时的时间戳。 最大大小设置为10,并且具有get,put和delete方法。 还有一个调整大小的方法,Aspect将调用此方法,稍后我们将进行检查。

  3. 调整建议
    package com.aranin.spring.aop;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class ResizeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("invoking " + method.getName() + " on " + target.getClass() + " Object");if(method.getName().equals("put")){System.out.println("before invoking " + method.getName());((MyCache)target).resize();}}
    }

    如您所见,这是建议之前的一种方法。 类实现MethodBeforeAdvice接口,该接口包含单个方法before()。 如果您检查该方法,则在我们调用put方法时,将检查rezise方法是否被调用。

  4. Spring上下文springaopdemo.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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.1.xsd"><bean id="resizeAdvice" class="com.aranin.spring.aop.ResizeAdvice" /><bean id="myCache" class="com.aranin.spring.aop.MyCache" /><bean id="myAOPCache"class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="myCache" /><property name="interceptorNames"><list><value>resizeAdvice</value></list></property></bean>
    </beans>

    如果您注意到上述xml文件,则MyCache和ResizeAdvice都已注册为spring bean。 文件中的主要bean是myAOPCache。 这是spring aop在核心类上应用建议后创建的代理对象。 代理对象由ProxyFactoryBean类创建。 我们将myCache对象的引用传递给代理对象,并注册所有将应用于代理类的建议。

  5. 最后,让我们检查Client,这将有助于我们运行此演示。
    package com.aranin.spring.aop;import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;public class MyCacheClient {public static void main(String[] args){ApplicationContext springcontext = new FileSystemXmlApplicationContext("D:/samayik/SpringDemos/src/main/resources/springaopdemo.xml");MyCache myCache = (MyCache)springcontext.getBean("myAOPCache");myCache.put("1", "1");myCache.put("2", "2");myCache.put("3", "3");myCache.put("4", "4");myCache.put("5", "5");myCache.put("6", "6");myCache.put("7", "7");myCache.put("8", "8");myCache.put("9", "9");myCache.put("10", "10");System.out.println((String)myCache.get("1"));System.out.println((String)myCache.get("2"));System.out.println((String)myCache.get("10"));myCache.put("11", "11");System.out.println((String)myCache.get("1"));System.out.println((String)myCache.get("2"));System.out.println((String)myCache.get("10"));System.out.println((String)myCache.get("11"));}}

    在该类中,我们启动spring容器并加载spingaopdemo.xml中存在的bean。 我们在缓存中推送10个对象,当我们尝试推送第11个对象时,第一个对象被删除并插入第11个对象。 输出很大,所以我没有发布输出。 上课并检查输出是否令您满意。

摘要

在这篇文章中,我们学习了如何使用面向方面的编程更好地处理交叉问题。 AOP是一个强大的概念,它使我们可以编写更清晰和更分离的代码。 AOP不提供任何新内容。 它所做的只是将业务逻辑与系统必须执行的其他普通任务分离。 它可以重用实现系统范围内交叉关注点的代码。 我们还学习了与AOP相关的各种术语。 最后但并非最不重要的一点是,我们看到了一个简单的示例,在该示例中,我们使用Spring AOP创建了一个简单的方法前建议,并将其应用于管理缓存系统。

注意

您可以自由使用和分发此代码中开发的缓存系统。 尽管不建议在生产系统中使用它。

一如既往,我一直希望这篇文章作为集体学习的启动平台,随意发表一两个关于您对AOP的看法以及如何计划在代码中使用它的评论。 祝您阅读愉快。

参考: Weblog4j博客上来自我们JCG合作伙伴 Niraj Singh的Spring面向方面编程 。

翻译自: https://www.javacodegeeks.com/2013/10/aspect-oriented-programming-with-spring-2.html

Spring面向方面的编程相关推荐

  1. spring 面向接口编程_Spring面向方面的编程

    spring 面向接口编程 介绍 在理想的面向对象系统中,我们希望将每个对象设计为执行一项特定任务. 但是,除了执行其主要任务之外,对象还执行被动任务,例如日志记录,事务,安全性,缓存等.这些被动活动 ...

  2. Spring 详解(三):AOP 面向切面的编程

    AOP即面向切面编程,它通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型. ...

  3. Spring面向切面编程

           JAVA就业套餐课:https://edu.csdn.net/combo/detail/1230 第1章主要介绍了Spring管理实体对象的应用,通过ApplicationContext ...

  4. 使用Spring AOP进行面向方面的编程

    面向方面的编程(AOP)是指将辅助功能或支持功能与主程序的业务逻辑隔离开来的编程范例. AOP是用于分离横切关注点的有前途的技术,这在面向对象的编程中通常很难做到. 以此方式增加了应用程序的模块化,并 ...

  5. Spring面向切面编程(AOP)详解

    Spring面向切面编程(AOP)详解 面向切面编程(AOP)是Spring框架的另外一个重要的核心内容. 而在讲AOP之前,先来了解一下动态代理这个概念,因为AOP基于动态代理. 动态代理概念:在程 ...

  6. javaee编程题_在JavaEE中使用CDI的简单面向方面的编程(AOP)

    javaee编程题 我们编写满足特定业务逻辑的服务API. 涵盖所有服务API(如安全性,日志记录,审核,度量延迟等)的跨领域问题很少. 这是一个重复的非业务代码,可以在其他方法之间重用. 重用的一种 ...

  7. 面向切面编程应用_应用面向方面的编程

    面向切面编程应用 1.引言 面向方面编程的主要目标是将跨领域关注点分离. 当我们谈论跨领域的关注时,我们指的是在我们的系统或应用程序中的多个地方使用的通用功能. 这些概念包括: 记录中 交易管理 错误 ...

  8. 在JavaEE中使用CDI的简单面向方面的编程(AOP)

    我们编写满足特定业务逻辑的服务API. 涵盖所有服务API(如安全性,日志记录,审核,度量延迟等)的跨领域问题很少. 这是一个重复的非业务代码,可以在其他方法之间重用. 重用的一种方法是将这些重复的代 ...

  9. SpringAop篇 (2) Spring中的切面编程技术 AspectJ

    介绍 : AOP(Aspect Orient Programming) 既为面向切面编程. 它可以说是OOP编程的一种扩展与补充,可以较为友好的处理不同模块之间具有横向相关性质的一类问题,比如日志管理 ...

最新文章

  1. [Android Pro] AndroidX重构和映射
  2. 基于WINCE6.0下载multiple XIP镜像文件
  3. Jquery工作常用实例——隐藏功能实现
  4. DOM克隆操作(深克隆/浅克隆)
  5. mysql函数 字符长度限制_MySQL中使用group_concat()函数数据字符过长报错的问题解决方法...
  6. HTML 5 input placeholder 属性 实现搜索框提示文字点击输入后消失
  7. 区块链 fisco bcos webase-front docker方式部署
  8. 静态代码编码安全审计: PHP源代码审计工具RIPS
  9. Linux nohup命令详解
  10. Linux如何修改主机名hostname
  11. 【linux内核分析与应用-陈莉君】内核同步概述
  12. 51单片机和315M无线发射模块编码与解码
  13. redis如何查看版本号?
  14. 二手书交易平台备受资本青睐 打造小而美的市场会不会一帆风顺?
  15. vncserver: Wrong type or access mode
  16. 思科交换机配置单播MAC地址过滤
  17. 三菱伺服器J3、J4、JE中文调试软件
  18. 2021年P气瓶充装考试题及P气瓶充装考试内容
  19. Uedit32比较2个文件的内容
  20. web 端 调取导航总结

热门文章

  1. Invalid character found in the request target. The valid characters are defi
  2. 如何在Intellij IDEA中集成Gitlab
  3. X86汇编语言中的registers相关
  4. 单列集合Set的实现类TreeSet
  5. jsr303 spring_使用Spring和JSR 303进行方法参数验证
  6. apigee 安装_APIGEE:用于API代理的CI / CD管道
  7. ubuntu安装jdk语句_JDK 12:实际中的切换语句/表达式
  8. java改变变量编码方式_Java 10将如何改变您的编码方式
  9. datastore_使用Spring Session和JDBC DataStore进行会话管理
  10. 应用程序缓存_应用程序模块和实体缓存