AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。

  

AOP 的应用范围

  传统的程序通常表现出一些不能自然地适合单一的程序模块或者是几个紧密相关的程序模块的行为,AOP 将这种行为称为横切,它们跨越了给定编程模型中的典型职责界限。横切行为的实现都是分散的,软件设计师会发现这种行为难以用正常的逻辑来思考、实现和更改。最常见的一些横切行为如下面这些:

 

  日志记录,跟踪,优化和监控

 

  事务的处理

 

  持久化

 

  性能的优化

 

  资源池,如数据库连接池的管理

 

  系统统一的认证、权限管理等

 

  应用系统的异常捕捉及处理

 

  针对具体行业应用的横切行为

Spring 为解耦而诞生,其中AOP(面向切面编程)是很浓重的一笔。

这里简单记录一下AOP 给我带来的好处:

1.

用了一段时间,想通过简单的代码,更好的阐述以及理解它。

以前:假设我们有个简单的业务,还是经典的Hello World,那么我们定义一个Service 接口,一个ServiceImpl 实现类,一个sayHello 方法,这里使用网上很经典的日志记录的例子。

1.Service接口:定义一个sayHello  的业务方法

2.ServiceImpl实现类:主要是打印HelloWord,但是日常项目中,在主要业务前后可能会添加日志记录,或者开启事务等其他必要操作。

  1. public class ServiceImpl implements Service{  
    
        @Override
    public void sayHello() {
    System.out.println("前置日记:打印、启动事务等..");
    System.out.println("Hello world!");
    System.out.println("后置日记:打印、关闭事务等..");
    }
    }

例子很简单,那么假设,我们不光拥有sayHello ,还有sayBye 等多个方法,并且都需要其他操作呢?那么你是不是会写很多个这样的,重复的代码?

当然,你可以减少一部分工作量,你可以这样:

  1. public class ServiceImpl implements Service{  
    
        @Override
    public void sayHello() {
    before();
    System.out.println("Hello world!");
    after();
    } @Override
    public void sayBye() {
    before();
    System.out.println("Bye bye!");
    after();
    } public static void before(){
    System.out.println("前置日记:打印、启动事务等..");
    } public static void after(){
    System.out.println("后置日记:打印、关闭事务等..");
    }
    }

我们再次假设,如果我们拥有更多的业务方法:sayHi(),sayOther()....,需要更多的其他操作:打印信息,传输记录....。并且其他ServiceImpl 里面的方法也需要这些方法呢?那么我们是不是每个类又要继续添加呢?

当然,你可以这样做:建立一个对Service 添加额外功能的类,统一提供。

  1. public class ServiceFactory {
    public static void before(){
    System.out.println("前置日记:打印、启动事务等..");
    } public static void after(){
    System.out.println("后置日记:打印、关闭事务等..");
    } public static void other(){
    System.out.println("做其他的事..");
    }
    }

ServiceImpl 就成这样:

  1. public class ServiceImpl implements Service{  
    
        @Override
    public void sayHello() {
    ServiceFactory.before();
    System.out.println("Hello world!");
    ServiceFactory.after();
    } @Override
    public void sayBye() {
    ServiceFactory.before();
    System.out.println("Bye bye!");
    ServiceFactory.after();
    } @Override
    public void sayHi() {
    ServiceFactory.before();
    System.out.println("Hi");
    ServiceFactory.after(); ServiceFactory.other();
    }
    }

这样代码,感觉是少了一些,但是我们的原则是尽量 别重复同样的代码,提高代码的复用性,改动最小为基准。也许业务很复杂,比较多,那么你要重复多少代码,整个类要写得多麻烦所啊!如果到时候有些假设before 和after 需要变化位置,你又要改动多少呢?

当然,目前的的JDK (大于1.3)为了解决这些问题,为我们提供的反射机制,动态代理机制。看看如何更好的解决这个问题。这里先copy 下,什么是代理:

Java的动态代理机制
代理模式是常用的Java设计模式。代理类主要负责为委托类预处理消息、过滤信息、把消息转发给委托类,以及事后处理信息等。
    理论 - -总是那么抽象(~。~),简单点说,就是:1.我的目的是去学校,那么校服 早餐 校车,这些我都需要,但是不由我做,全部代理给我父母搞定了(当然我是自己搞定的。)2.再简单的说就是:我只关注我主要的事情,其他附加的事情,全部交给别人搞定。看代码..

MyPorxy 我的代理类:

  1. import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy; public class MyProxy implements InvocationHandler{ // 目标对象,也就是我们主要的业务,主要目的要做什么事
    private Object delegate; /**
    * 和你额外需要做得事情,进行绑定,返回一个全新的对象(写法,基本上固定的)
    * @param delegate
    * @return
    */
    public Object bind(Object delegate){
    this.delegate = delegate;
    return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(),
    this.delegate.getClass().getInterfaces(), this);
    } /**
    * 你刚才需要执行的方法,都需要通过该方法进行动态调用
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    Object obj = null;
    // 执行前置的方法
    ServiceFactory.before();
    // 通过反射,执行目标方法,也就是你的主要目的
    obj = method.invoke(this.delegate, args);
    // 执行后置的方法
    ServiceFactory.after();
    // 返回值给调用者
    return obj;
    } }

这里运用的反射知识,还需要去看看,这里就不解释了。

ServiceImpl 变化:

  1. public class ServiceImpl implements Service{  
    
        @Override
    public void sayHello() {
    System.out.println("Hello world!");
    } @Override
    public void sayBye() {
    System.out.println("Bye bye!");
    } @Override
    public void sayHi() {
    System.out.println("Hi");
    }
    }

测试类:

  1. public class Test {  
    
        /**
    * 测试类
    * @param args
    */
    public static void main(String[] args) {
    // 不启用代理
    //Service service = new ServiceImpl();
    // 使用代理
    Service service = (Service)new MyProxy().bind(new ServiceImpl()); service.sayHello();
    service.sayBye();
    service.sayHi();
    }
    }

OK,那么你现在看看,我们的业务实现类ServiceImpl 是不是干净多了,代码是不是在某些地方见过呢?即时你再进行添加更多的方法,也可以同样实现了对吗?当然,在Test里面,假设我们有的方法想用,有的方法不想用,那么又该怎么实现呢?

Spring AOP 学习(一) 代理模式的更多相关文章

  1. Spring AOP 和 动态代理技术

    AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...

  2. Spring AOP 学习例子

    http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example     工作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大 ...

  3. Spring AOP学习笔记

      Spring提供了一站式解决方案:          1) Spring Core  spring的核心功能: IOC容器, 解决对象创建及依赖关系          2) Spring Web ...

  4. 在Intellij上面导入项目 & AOP示例项目 & AspectJ学习 & Spring AoP学习

    为了学习这篇文章里面下载的代码:http://www.cnblogs.com/charlesblc/p/6083687.html 需要用Intellij导入一个已有工程.源文件原始内容也可见:link ...

  5. AOP和spring AOP学习记录

    AOP基本概念的理解 面向切面AOP主要是在编译期或运行时,对程序进行织入,实现代理, 对原代码毫无侵入性,不破坏主要业务逻辑,减少程序的耦合度. 主要应用范围: 日志记录,性能统计,安全控制,事务处 ...

  6. 深入理解Spring AOP之二代理对象生成

    深入理解Spring AOP之二代理对象生成 spring代理对象 上一篇博客中讲到了Spring的一些基本概念和初步讲了实现方法,当中提到了动态代理技术,包含JDK动态代理技术和Cglib动态代理 ...

  7. 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)

    Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...

  8. Spring AOP学习笔记04:AOP核心实现之创建代理

    上文中,我们分析了对所有增强器的获取以及获取匹配的增强器,在本文中我们就来分析一下Spring AOP中另一部分核心逻辑--代理的创建.这部分逻辑的入口是在wrapIfNecessary()方法中紧接 ...

  9. AOP 技术原理——代理模式全面总结

    前言 非常重要的一个设计模式,也很常见,很多框架都有它的影子.定义就不多说了.两点: 1.为其它对象提供一个代理服务,间接控制对这个对象的访问,联想 Spring 事务机制,在合适的方法上加个 tra ...

随机推荐

  1. HugePage简介和KVM中使用HugePage

    现在,有许多的处理器架构都支持多种的内存页大小,其中就包括比一般的page size大很多的huge page.就目前来说,尽管在个人电脑中基本都实现了对huge page的支持,然而,huge pa ...

  2. TPM概述

    TPM(Trusted Platform Module)安全芯片,是指符合TPM(可信赖平台模块)标准的安全芯片.标准由TCG(可信赖计算组织,Trusted Computing Group)提出,目 ...

  3. AD使用技巧

    1. 效果显示 3 显示3D效果,2显示2D效果. 2.  阻焊塞孔 双击过孔显示属性  solder Mask Expansions Force complete tenting on top Fo ...

  4. 阿里云服务器 端口开放问题 浏览器钟输入ip 访问服务器

    在这里先用一堆粗口强烈吐槽阿里云服务器控制台,屎一样的界面,简直非人类的操作.想找一个功能简直无从下手. 场景: 今天刚在阿里云买了个服务器,打算愉快的用五分钟将数据库,apache,安装完毕,然后去 ...

  5. Git使用技巧(3)-- 远程操作

    Git远程操作详解 作者: 阮一峰 编辑更新:shifu204 日期: 2016年9月1日 Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能. Git有很多优势,其中之一就是远程操 ...

  6. 1211日课后shell总结

      1211shell   作者:高波 归档:学习笔记 2017年12月11日13:10:56 快捷键: Ctrl + 1 标题1 Ctrl + 2 标题2 Ctrl + 3 标题3 Ctrl + 4 ...

  7. 苯(Benzene)

    在常温下是甜味.可燃.有致癌毒性的无色透明液体,其密度小于水,但分子质量大于水,并带有强烈的芳香气味.它难溶于水,易溶于有机溶剂,本身也可作为有机溶剂.苯是一种石油化工基本原料,其产量和生产的技术水平 ...

  8. Spring4 MVC+Hibernate4+MySQL+Maven使用注解集成实例

    在本教程中,我们将使用基于注解的配置集成Spring和Hibernate. 我们将开发包含表单要求用户输入一个简单的CRUD为导向Web应用程序,使用Hibernate保存输入的数据到 MySQL 数 ...

  9. python 自动化之路 day 20 Django进阶/BBS项目【一】

    一.django进阶 1.django orm 增删改查 1.1.创建表: 1 2 3 >>> from blog.models import Blog >>> b ...

  10. 进程 vs. 线程

    我们介绍了多进程和多线程,这是实现多任务最常用的两种方式.现在,我们来讨论一下这两种方式的优缺点. 首先,要实现多任务,通常我们会设计Master-Worker模式,Master负责分配任务,Work ...