spring 面向接口编程

介绍

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

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

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

遗产

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

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

代表团

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

委派==繁琐

面向方面的编程

这是否意味着我们要喝汤了。 相反,这给我们留下了第三种也是最好的方法,即面向方面的编程。 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"));}}

    在此类中,我们启动弹簧容器并加载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 面向接口编程

spring 面向接口编程_Spring面向方面的编程相关推荐

  1. 理解Spring面向接口编程思想

    我们都知道java是面向对象的语言: 一个人是一个对象一个物品也是一个对象: 在刚刚接触Spring的时候只知道用Spring来管理咱们的一个个对象,一直知道Spring 提倡的面向接口的编程方式,经 ...

  2. 面向接口编程的优点_为什么我们要面向接口编程

    到底面向?编程 面向过程编程( ProcedureOriented.简称 PO) 和 面向对象编程( ObjectOriented.简称 OO) 我们一定听过,然而实际企业级开发里受用更多的一种编程思 ...

  3. python面向接口编程_Python 中的面向接口编程

    前言 "面向接口编程"写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性.维护性谁都不能拒绝 ...

  4. 问题小结(二)——maven的核心功能、面向对象编程和面向接口编程的区别、抽象类和接口的区别等

    文章目录 1. Java创建对象有哪四种方式? 2. 什么是maven?maven的核心功能有哪些? 3. 什么是MVC?说说分层的好处. 4. Spring的两大核心技术是什么? 5. 什么是IOC ...

  5. 2014-03-11 Spring的学习(3)------面向切面编程(AOP)

    2019独角兽企业重金招聘Python工程师标准>>> 1. AOP概念 首先让我们从一些重要的AOP概念和术语开始.这些术语不是Spring特有的.不过AOP术语并不是特别的直观, ...

  6. 什么是面向接口编程、面向过程编程、面向对象编程?

    1.什么是面向接口编程?(IOP) 面向接口编程(Interface Oriented Programming:IOP)是一种编程思想,接口作为实体抽象出来的一种表现形式,用于抽离内部实现进行外部沟通 ...

  7. 编程思想——面向接口编程(Java语言)

    简介 最近学习Java基础的时候被面向接口编程的思想迷住了,自己研究了好一会才搞明白,面向接口太伟大了,我将用我写的第一篇文章记录下这个思想的过程.接下来将通过一个通俗的例子阐述面向接口编程的便利性, ...

  8. 面向接口编程详解(二)——编程实例

    作者: T2噬菌体  来源: 博客园  发布时间: 2012-06-09 12:13  阅读: 19178 次  推荐: 25   原文链接   [收藏]   通过上一篇文章的讨论,我想各位朋友对&q ...

  9. 面向接口编程和面向对象编程的区别

    我想,对于各位使用面向对象编程语言的程序员来说,"接口"这个名词一定不陌生,但是不知各位有没有这样的疑惑:接口有什么用途?它和抽象类有什么区别?能不能用抽象类代替接口呢?而且,作为 ...

最新文章

  1. 免费!!3天,吃透JVM!(限时领)
  2. java定时器返回future_java 定时器线程池(ScheduledThreadPoolExecutor)的实现
  3. python开发需要掌握哪些知识-人工智能需要学习哪些专业课程知识?
  4. vi 技巧和诀窍:令人刮目相看的 10 个超酷命令
  5. 查看、关闭当前服务器上启动服务 / 进程
  6. 插件 KSImageNamed 用图片时自动显示图片缩略图
  7. 设计素材psd分层模板|临摹搞定促销海报版式!
  8. python3随机生成数字_五种方法实现python3-随机生成10位包含数字和字母的密码
  9. Atitit 2016 技术趋势与没落技术 目录 1.1. 离线优先Web应用程序(Offline first web applications) 1 1.2. 依照产品而不是项目(product
  10. Subclipse in Eclipse的安装和使用
  11. ssh 整合TOMCAT启动遇到错误
  12. 网页设计中的色彩搭配技巧
  13. python 线程锁_Python线程锁的实现
  14. 催眠曲用计算机怎么弹,在电脑中巧播“催眠曲”
  15. 迪科斯特拉算法(Dijkstra Algorithm)
  16. 如何解决Namespace declaration statement has to be the very first statement or after any declare call
  17. 哨向 Mika Lelush 2
  18. 面经八之牛客网面经整理
  19. STC89C51单片机:keil5与stc-isp的下载与安装
  20. Vscode批量处理

热门文章

  1. 【动态规划】大厅安排 (ssl 1212)
  2. 搜索训练1 [8数码问题]
  3. SpringBoot2.1.9 多数据源JDBC配置
  4. Java5泛型的用法,T.class的获取和为擦拭法站台
  5. Class类中的getEnclosingXX、getDeclaredXX
  6. 使用ueditor实现多图片上传案例
  7. php 编写线程教程,php 实现多线程
  8. java 单例 生命周期_单例模式--- 声明周期托管方式
  9. python简短语法_写出优雅简洁的 python 语法(二)函数传参
  10. 如何设置电脑自动锁屏_这个手机锁屏密码竟可以根据时间而变化!密码每分钟都会发生改变...