spring框架的核心之一AOP,面向切面编程是一种编程思想。我对于面向切面编程的理解是:可以让我们动态的控制程序的执行流程及执行结果。spring框架对AOP的实现是为了使业务逻辑之间实现分离,分离主业务逻辑及次要业务逻辑,进而降低系统间的耦合度。

spring框架对于这种编程思想的实现基于两种动态代理模式,分别是 JDK动态代理 及 CGLIB的动态代理,这两种动态代理的区别是 JDK动态代理需要目标对象实现接口,而 CGLIB的动态代理则不需要。下面我们通过一个实例来实现动态代理,进而帮助我们理解面向切面编程。

需求:实现一个除法运算器,要求计算出两个整数相除的商,其中除数为0时提示用户"除数不能为零"并返回-1,被除数为0零时直接返回0。

我们来看一下一般的做法。

public int division(int a,int b){
if(b == 0){
System.out.println("除数不能为0");
return -1;
}else if(a == 0){
return 0;
}else{
return a/b;
} }

我们来分析一下需求,“计算出两个整数相除的商”是我们的主业务逻辑,而“除数为0时提示用户"除数不能为零"并返回-1,被除数为0零时直接返回0”是我们的次要业务逻辑,以上的做法无疑是吧,主业务逻辑和次要业务逻辑偶合到了一块。这里只是做了一个除法,可当你的主业务逻辑本身就就比价复杂的,再这样做的话就会增加代码的偶合度及可读性。

下面我们使用 JDK的 动态代理来实现以上的需求,虽然以下的做法看起来像是杀鸡用牛刀,但我们这里只是为了说明问题。

JDK的动态代理要使用到一个类 Proxy 用于创建动态代理的对象,一个接口 InvocationHandler用于监听代理对象的行为,其实动态代理的本质就是对代理对象行为的监听。

首先我们需要提供一个主业务逻辑的接口,这 JDK动态代理实现的先决条件。

public interface IDivisionService {

    int division(int a ,int b);
}

下面是实现类(实现类中只有主页业务逻辑)

public class DivisionServiceImpl implements IDivisionService {

    @Override
public int division(int a, int b) { return a/b;
} }

下面我们来看一下动态代理是怎么分离主业务逻辑和次要业务逻辑的。

首先准备一个创建代理对象的工厂类

public class BeanFactory {

    public static Object getAgencyObj(final Object target){

        Object agencyObj = null;

        agencyObj = Proxy.newProxyInstance(
//获取目标对象类的加载器
target.getClass().getClassLoader(),
//获取对象接口的Class对象数组
target.getClass().getInterfaces(),
//一个内部类,用于创建监听对象
new InvocationHandler() {
/**
* 通过反射机制获得实现类中方法的实例 method 及方法的参数 args 这取决于代理对象 agencyObj调用了那个方法。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
int a = (int)args[0];
int b = (int)args[1];
//用于处理次要业务逻辑
if(b == 0){
System.out.println("除数不能为0");
return -1;
}
//用于处理次要业务逻辑
if(a == 0){
return 0;
}
//执行主业务逻辑
Object result = method.invoke(target, args);
return result;
}
}); return agencyObj;
} }

最后测试类:

public class MyTest {
public static void main(String[] args) {
//创建目标类
IDivisionService target = new DivisionServiceImpl();
//创建代理对象
IDivisionService agencyObj = (IDivisionService)BeanFactory.getAgencyObj(target);
int consult = agencyObj.division(0, 2);
System.out.println("两数相除商为--->"+consult); }
}

在这里我们看到,除法计算器的实现类DivisionServiceImpl 只是来做除法这一主业务逻辑,而 “除数为0时提示用户"除数不能为零"并返回-1,被除数为0零时直接返回0”这一次要业务逻辑交由JDK的动态代理来实现。

  最后说一点,我们作为程序员,研究问题还是要仔细深入一点的。当你对原理了解的有够透彻,开发起来也就得心应手了,很多开发中的问题和疑惑也就迎刃而解了,而且在面对其他问题的时候也可做到触类旁通。当然在开发中没有太多的时间让你去研究原理,开发中要以实现功能为前提,可等项目上线的后,你有大把的时间或者空余的时间,你大可去刨根问底,深入的去研究一项技术,为觉得这对一名程序员的成长是很重要的事情。

spring5——Aop的实现原理(动态代理)的更多相关文章

  1. AOP的实现原理——动态代理

    IOC负责将对象动态的 注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果,可谓是招之则来,挥之则去.想想都觉得爽,如果现实生活中也有这本事那就爽 歪歪了,至于有多爽,各位自己脑 ...

  2. 菜鸟学SSH(十四)——Spring容器AOP的实现原理——动态代理

    之前写了一篇关于IOC的博客——<Spring容器IOC解析及简单实现>,今天再来聊聊AOP.大家都知道Spring的两大特性是IOC和AOP,换句话说,容器的两大特性就是IOC和AOP. ...

  3. 浅析Spring中AOP的实现原理——动态代理

    一.前言   最近在复习Spring的相关内容,刚刚大致研究了一下Spring中,AOP的实现原理.这篇博客就来简单地聊一聊Spring的AOP是如何实现的,并通过一个简单的测试用例来验证一下.废话不 ...

  4. Spring 容器AOP的实现原理——动态代理

    参考:http://wiki.jikexueyuan.com/project/ssh-noob-learning/dynamic-proxy.html(from极客学院) 一.介绍 Spring的动态 ...

  5. Spring容器AOP的实现原理——动态代理(转)

    文章转自http://blog.csdn.net/liushuijinger/article/details/37829049#comments

  6. Hibernate学习--hibernate延迟加载原理-动态代理(阿里电面)

    在正式说hibernate延迟加载时,先说说一个比较奇怪的现象吧:hibernate中,在many-to-one时,如果我们设置了延迟加载,会发现我们在eclipse的调试框中查看one对应对象时,它 ...

  7. 新秀学习SSH(十四)——Spring集装箱AOP其原理——动态代理

    之前写了一篇文章IOC该博客--<Spring容器IOC解析及简单实现>,今天再来聊聊AOP.大家都知道Spring的两大特性是IOC和AOP. IOC负责将对象动态的注入到容器,从而达到 ...

  8. Spring AOP实现原理-动态代理

    目录 代理模式 静态代理 动态代理 代理模式 我们知道,Spring AOP的主要作用就是不通过修改源代码的方式.将非核心功能代码织入来实现对方法的增强.那么Spring AOP的底层如何实现对方法的 ...

  9. 二)Spring AOP编程思想与动态代理

    一.aop编程思想 1.面向切面,就是能够不动源码的情况下,从横切面切入新的代码功能. 2.实现原理是动态代理 动态代理的步骤 a.写生产厂家,实现接口,代理只能代理接口 b.动态代理类实现Invoc ...

随机推荐

  1. MapReduce浅析

    很早之前就用过Hadoop,但对MapReduce中的具体数据流向过程一直不甚明了,用Python Streamming的方式写了几个MapReduce,对这个过程有了一定的认识. 首先我们知道,Ma ...

  2. Python 3 中生成器函数yield表达式的使用

    生成器函数或生成器方法中包含了一个yield表达式.调用生成器函数时,会返回一个迭代子,值从迭代子中每次提取一个(通过调用其__next__()方法).每次调用__next__()时,生成器函数的yi ...

  3. 需求分析--WBS

    我们的软件天气预报的WBS如下:

  4. JS面向对象与面向过程

    前言 面向对象编程: 就是将你的需求抽象成一个对象,然后针对这个对象分析其特征(属性)与动作(方法)--这个对象就称之为类 面向过程编程: 特点:封装,就是将你需要的功能放在一个对象里面 ------ ...

  5. float与double的精度和范围

    1 范围 float和double的范围是由指数的位数来决定的. float的指数位有8位,而double的指数位有11位,分布如下: float: 1bit(符号位) 8bits(指数位) 23bi ...

  6. 缺少libssl.so.4文件

    1.报错代码: /usr/local/pureftpd/sbin/pure-ftpd: error while loading shared libraries: libssl.so.4: wrong ...

  7. 制作Linux登录欢迎界面

    1.登录提示语: 将提示语写入/etc/motd 文件 _ooOoo_ o8888888o 88" . "88 (| -_- |) O\ = /O ____/`---'\____ ...

  8. 关于synchronized与volatile的小析

    简单点说:synchronized很强大,既可以保证原子性,也可以保证可见性,而volatile不能保证原子性: 可见性:一个线程对共享变量值的修改,能够及时的被其它线程看到. 共享变量:如果一个变量 ...

  9. Oracle查询优化改写--------------------报表和数据仓库运算

    一.行转列 二.列传行 '

  10. RabbitMQ 通信过程

    Rabbit MQ的通信过程 MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,是消费-生产者模型的典型的代表,producer往消息队列中不断写入消息,而另一端consume ...