java面向切面编程

java面向切面编程面向切面在英文中的单词是 AspectOrient AOP 在 spring 框架中叫 aop 它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术 它是一种新的方法论 它是对传统 OOP 编程的一种补充 AOP 技术是建立在 Java 语言的反射机制与动态代理机制之上的 请看下图以上图是利用 jdk 动态代理为真实对象上的

面向切面在英文中的单词是Aspect Oriented Programming(AOP),在spring框架中叫aop,它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。

AOP技术是建立在Java语言的反射机制与动态代理机制之上的。请看下图

java面向切面编程

以上图是利用jdk动态代理为真实对象上的每个方法上加上日志功能。从这张图中可以看出,我们是面向真实对象上的方法编程,把方法切开,在执行方法之前做了日志功能。但是在实际开发中,我们不会把日志代码写死在程序里面,我们会把切面的代码用对象的形式进行封装,以对象的形式传递参数,然后执行对象,就是执行了切面的代码,这就是在面向切面编程。

在实际开发中,这种面向切面编程通常用在做系统的日志记录,权限管理和,事物管理等功能,这样做的好处是让j2ee程序员在编写具体的业务逻辑出来方法时,只需关心具体业务逻辑的实现,既提高了工作效率,又使代码变得简洁优雅。

下面我以这样的一个例子讲解:在系统的执行过程中,要求在用户每次调用service层的每个方法时,在控制台打印出调用的方法名称以及调用该方法的次数,代码实现如下:

package cn.lmj.aop; //service层接口 public interface UserService { public void run(); public void eat(); } package cn.lmj.aop; //service层接口实现类 public class UserServiceImpl implements UserService { public void run() { System.out.println("run............."); } public void eat() { System.out.println("eat............"); } } package cn.lmj.aop; import java.lang.reflect.Method; //利用接口定义一种契约 public interface Advice { void beforeMethod(Method m); } package cn.lmj.aop; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; //把切面的代码封装成为对象 public class MyAdvice implements Advice { private Map map = new HashMap (); public void beforeMethod(Method m) { if(map.containsKey(m.getName())) { Integer i = map.get(m.getName()); i++; System.out.println(m.getName()+"被执行了"+(i)+"次"); map.put(m.getName(),i); } else { map.put(m.getName(), 1); System.out.println(m.getName()+"被执行了1次"); } } } package cn.lmj.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class BeanFactory { //接受目标和建议,产生任意类(只要该类有接口)的代理类,拦截所有的方法访问 public static Object getPerson(final Object obj,final Advice advice) { Object proxy = Proxy.newProxyInstance(BeanFactory.class.getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object arg0, Method m, Object[] arg2) throws Throwable { advice.beforeMethod(m); Object value = m.invoke(obj, arg2); return value; } }); return proxy; } } package cn.lmj.aop; public class Demo { public static void main(String[] args) { //必须保证MyAdvice的实例全局只有一份 MyAdvice advice = new MyAdvice(); UserService c = (UserService) BeanFactory.getPerson(new UserServiceImpl(),advice); c.eat(); c.eat(); c.eat(); c.eat(); c.run(); c.run(); c.run(); //执行结果: /* eat被执行了1次 eat............ eat被执行了2次 eat............ eat被执行了3次 eat............ eat被执行了4次 eat............ run被执行了1次 run............. run被执行了2次 run............. run被执行了3次 run............. */ } } 

上面的代码关键之处是BeanFactory的getPerson()方法的实现,接受任意的类(只要该类有接口实现),并把切面的代码以对象的方式进行传递,这样做能够使得我们编程人员更加关心具体业务代码的实现,我们只需获取Service层对象的时候从工厂中获得代理对象,这个对象就比原来的对象功能更强大。

我们做系统在使用了spring框架之后会发现这样一种场景,我们写好了一个对象,然后往spring容器里一放,然后再取出来,结果这个对象就比以前强大很多,比如这个对象自动拥有了事物管理功能,日志记录功能等,它是怎么做到的?其实和我上面写的原理上差不多,只要上面的例子懂,spring的aop再无秘密可言。但是有一定要注意,在实际开发中我们很多对象是服务器给我们的,如果这个对象没有实现接口,那它怎么产生代理类?spring用到了CGLIB这套api,它是基于子类的方式产生代理,这里不做描述。还有一点,在开发中,如果一个类即没有实现接口,又是final的,那么它就不能产生代理类。



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/226679.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午10:22
下一篇 2026年3月16日 下午10:22


相关推荐

  • Python阶乘求和

    Python阶乘求和题目:获得用户输入的整数n,输出1!+2!+…+n!的值。思路:依次计算每个阶乘的值,然后相加起来,即可得到结果代码:#获得用户输入的整数n,输出1!+2!+…+n!的值。num=int(input(“pleaseinputanumber:”))num_sum=0foriinrange(1,num+1):forjinrange(1,i+1):num_sum=num_sum+jprint(f”1!+…+{num}!的阶乘

    2025年8月18日
    5
  • 训练过程–Batchsize(总之一般情况下batchsize能设多大就设多大)[通俗易懂]

    尽可能地设大batchsize "LargeBatchLargeBatch在keypoints上也是有用的,大概能提到0.4到0.3的点的AP。"在利用ImageNet训练AlexNet模型时,其中每GPU的最优批量大小为512。如果我们希望使用大量GPU并保证每GPU皆拥有理想的执行效率,则应当将批量大小设定为16×512=8192。 "Tra…

    2022年4月18日
    37
  • Android代码混淆之混淆规则

    Android代码混淆之混淆规则因为Android是使用Java开发的,所以开发者可以使用ProGuard对代码进行混淆。SDK已经集成了ProGuard工具,开发者可以从SDK目录下的\tools\proguard目录中进行查看。    ProGuard是一个免费的Java类文件收缩,优化,混淆和预校验器。它可以检测并删除未

    2022年5月30日
    28
  • 腾讯元宝弹窗在哪删除

    腾讯元宝弹窗在哪删除

    2026年3月13日
    3
  • Java基础–单链表的实现[通俗易懂]

    Java基础–单链表的实现[通俗易懂]Java内部也有自己的链表–LinkedList,但是我们今天不是讨论LinkedList,而是自己来实现一个单链表,包括简单的增删查改,以及使用链表来实现栈和队列这两种数据结构,涉及的方面如下: 单链表的结构 单链表的基本操作 使用虚拟头结点的单链表 单链表实现栈 单链表实现队列 单链表的结构 一种链式存取的数据结构,单链表中的数据是以结点的形式存在,每一个结点…

    2022年6月14日
    27
  • 出口押汇贷款_出口贸易融资业务

    出口押汇贷款_出口贸易融资业务出口商贸易融资工具:出口单据质押贷款出口单据质押贷款:是指进口商与出口商约定以汇款结算方式签订贸易合同,出口商在将货物装运上船,报关之后,将全套正本海运提单质押银行申请贷款,等到进口商付款之后,再将全套正本海运提单寄给进口商。特色:(1)无须其他担保,货物无权质押给银行即可实现资金周转,加速资金流通,给出口商经营带来便利,同时可以规避汇率风险。(2)融资方式简单,方

    2026年2月7日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号