关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »手把手教你用Java实现AOP

    手把手教你用Java实现AOP

    2015-03-29 00:00:00 出处:codeceo
    分享

    介绍

    众所周知,AOP(面向切面编程)是Spring框架的特色功能之一。通过设置横切关注点(cross cutting concerns),AOP提供了极高的扩展性。那AOP在Spring中是怎样运作的呢?当你只能使用core java,却需要AOP技术时,这个问题的解答变得极为关键。不仅如此,在高级技术岗位的面试中,此类问题也常作为考题出现。这不,我的朋友最近参加了一个面试,就被问到了这样一个棘手的问题——如何在不使用Spring及相关库,只用core Java的条件下实现AOP。因此,我将在ITJS的这篇文章中提供一份大纲,帮助大家了解如何只用core Java实现一个AOP(当然啦,这种AOP在功能上有一定的局限性)。注意,ITJS的这篇文章不是一篇有关Spring AOP与Java AOP的对比研究,而是有关在core Java中借助固有的设计模式实现AOP的教程。

    想必读者已经知道AOP是什么,也知道在Spring框架中如何使用它,因此ITJS的这篇文章只着眼于如何在不用Spring的前提下实现AOP。首先,我们得知道,Spring是借助了JDK proxy和CGlib两种技术实现AOP的。JDK dynamic proxy提供了一种灵活的方式来hook一个方法并执行指定的操作,但执行操作时得有一个限制条件:必须先提供一个相关的接口以及该接口的实现类。实践出真知,让我们透过一个案例来理解这句吧!现在有一个计算器程序,用于完成一些数学运算。让我们来考虑下除法功能,此时的问题是:如果core framework 已经具备了一份实现除法的代码,我们能否在代码执行时劫持(highjack)它并执行额外的校验呢?答案是肯定的,我将用下面提供的代码片段来证明这点。首先来看基础接口的代码:

     public interface Calculator {
        public int calculate( int a , int b);
    }

    该接口实现类的代码如下:

     public class CalculatorImpl implements Calculator {
        @Override
        public int calculate(int a, int b) {
            return a/b;
        }
    }

    假设我们既不能修该上面的代码,也不能对核心库进行任何改动,怎样才能完美地实现校验功能呢?不如试下JDK dynamic proxy的功能吧。

    public class SomeHandler implements InvocationHandler {
    
    // Code omitted for simplicity…..
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
    // Your complex business validation and logic
            Object result = method.invoke(targetObject ,params);
            return result;
        }
    
    }

    让我们通过测试类来看看由JDK dynamic proxy实现的校验功能的效果如何。

    public static void main(String[] args) {
            CalculatorImpl calcImpl = new CalculatorImpl();
            Calculator proxied = (Calculator)ProxyFactory.getProxy (Calculator.class, calcImpl, 
                    new SomeHandler(calcImpl));
            int result = proxied.calculate(20, 10);
            System.out.println("FInal Result :::" + result);
        }

    从结果可以看出,简单地实现功能强大的InvocationHandler接口,我们便能得到一个hooking implementation。按照JDK文档的描述,InvocationHandler接口是借助一个代理实例(proxy instance)来处理一个方法调用的。

    现在我们已经知道,InvocationHandler的invoke()方法能够帮助我们解决问题。那么再来解决一个新问题——怎样才能在方法执行的前后执行操作呢?说的更具体一些,我们能通过添加多个aop(before、after、around)来hook一个方法吗(译注:原文为add multiple aops,但我认为Handler是充当Aspect的角色)?答案同样是肯定的。按照以下的步骤建立一个精简的代码模板便能满足这样的需求:

    创建一个抽象类,用于将aop应用于目标对象上。 创建名为BeforeHandler 和 AfterHandler的两个aop。前者在方法执行之前工作,而后者则在方法执行结束后工作。 创建一个代理类,使所有的aop handler和目标对象只需作为参数传入,就能创建一个hook。 加入你自己的业务逻辑或者横切关注点。 最后,通过传入相关的参数创建代理对象(proxy object)。

    技术实现概要

    (译注:此处是核心代码片段,如果想运行该实例,需进入下方提供的链接下载完整代码)

    创建一个handler的抽象类:

    public abstract class AbstractHandler implements InvocationHandler {
    
    	private Object targetObject;
    
    	public void setTargetObject(Object targetObject) {
    		this.targetObject = targetObject;
    	}
    }

    创建名为BeforeHandler和AfterHandler的两个易扩展的handler抽象类:

    public abstract class BeforeHandler extends AbstractHandler {
    	public abstract void handleBefore(Object proxy, Method method, Object[] args);
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		handleBefore(proxy, method, args);
    		return method.invoke(getTargetObject(), args);
    	}
    }
    public abstract class AfterHandler extends AbstractHandler {
    	public abstract void handleAfter(Object proxy, Method method, Object[] args);
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		Object result = method.invoke(getTargetObject(), args);
    		handleAfter(proxy, method, args);
    		return result;
    	}
    }

    创建Proxy的工厂类:

    public class ProxyFactory {
    
    	public static Object getProxy(Object targetObject,
    			List handlers) {
    			//Code to get the proxy
    			return proxyObject;
    		} else {
    			return targetObject;
    		}
    	}
    }

    以下为测试代码:

    CalculatorImpl calcImpl = new CalculatorImpl();
    BeforeHandler before = new BeforeHandlerImpl();
    AfterHandler after = new AfterHandlerImpl();
    List<AbstractHandler> handlers = new ArrayList<AbstractHandler>();
    handlers.add(before);
    handlers.add(after);
    Calculator proxy = (Calculator) ProxyFactory.getProxy(calcImpl,
    				handlers);
    int result = proxy.calculate(20, 10);

    配置

    以上的代码片段简明扼要地解释了AOP在结构上的实现(structural implementation)。当然,如果能通过实际的测试将其运用到现实中去,那就再好不过了。读者可在下面的链接中获取完整的工程文件,并在Java编辑器中配置它们,最后通过其中的测试类来检验效果。

    https://github.com/debjava/aopusingjdkdynamicproxy

    总结

    希望这篇简短的有关AOP文章能够帮助到大家。需说明的是,ITJS的这篇文章只实现了before和after两种aop,而另外两种,即“Around”和“Throw”,则希望读者自行完成。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    电脑屏幕不小心竖起来了?别慌,快捷键搞定

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    IT头条

    Synology 更新 ActiveProtect Manager 1.1 以增强企业网络弹性和合规性

    00:43

    新的 Rubrik Agent Cloud 加速了可信的企业 AI 代理部署

    00:34

    宇树科技 G1人形机器人,拉动一辆重达1.4吨的汽车

    00:21

    Cloudera 调查发现,96% 的企业已将 AI 集成到核心业务流程中,这表明 AI 已从竞争优势转变为强制性实践

    02:05

    投资者反对马斯克 1 万亿美元薪酬方案,要求重组特斯拉董事会

    01:18

    技术热点

    大型网站的 HTTPS 实践(三):基于协议和配置的优化

    ubuntu下右键菜单添加新建word、excel文档等快捷方式

    Sublime Text 简明教程

    用户定义SQL Server函数的描述

    怎么在windows 7开始菜单中添加下载选项?

    SQL Server 2016将有哪些功能改进?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。