`
zhaoshg
  • 浏览: 257517 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring AOP面向切面编程

    博客分类:
  • java
阅读更多

spring里面有个概念叫aop(面向切面编程),很好很强大又很让人费解,很多开发人员会用并且天天挂在嘴边但是不理解其核心原理,今天周末有空,我想用一个小系列的文章给大家把aop分析清楚。要理解aop,首先要掌握java中的代理模式。

    在日常生活中,会遇到各种各样的中介机构,比如猎头公司,律师事务所,婚姻介绍所,房产公司等。在这些单位工作的人员均可称为代理人。代理人的共同特征是可以代替委托人去和第三方通信。譬如:律师代替委托人打官司,猎头代替委托人物色人才,红娘代替委托人寻找对象,房产代理人代替委托人出租房屋。

    代理人可以在第三方和委托人之间转发或过滤消息,但是不能取代委托人的任务。譬如你要找女朋友,委托你一要好的哥们去帮你物色,结果被他给物色了。这就不叫代理。

    代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

    代理模式一般涉及到的角色有:

    抽象角色:声明真实对象和代理对象的共同接口;

    代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

    真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

    我们来看个例子:

    package com.softeem.aop.staticProxy;

    /**

     * @author leno

     *抽象角色

     */

    public interface IHello {

      String greeting(String who);

    }

    package com.softeem.aop.staticProxy;

    /**

     * @author leno

     *真实角色

     */

    public class HelloImpl implements IHello {

     public String greeting(String who) {

                  System.out.println("greeting method is invoked.....");

                  return "hello,"+who;

           }

    }

    试想一下,如果这时候我们要对问候的业务逻辑方法进行日志记录。我们当然可以这样做:

    package com.softeem.aop.staticProxy;

    /**

     * @author leno

     *真实角色

     */

    public class HelloImpl implements IHello {

    private Logger logger = Logger.getLogger(this.getClass().getName());

     public void log(String message)

     {

      logger.log(Level.INFO, message);

     }

     public String greeting(String who) {

          log( "starting...");

           System.out.println("greeting method is invoked.....");

          log("stopping...");

           return "hello,"+who;

     }

    可问题来了,项目经理发话,不容许修改现存的类的实现。怎么办?这时候我们就要就想到代理模式了。我们再加一个代理类:

    静态代理类:

    package com.softeem.aop.staticProxy;

    import java.util.logging.Level;

    import java.util.logging.Logger;

    public class HelloLoggerProxy implements IHello {

     private Logger logger = Logger.getLogger(this.getClass().getName());

     private IHello helloImpl;

     public HelloLoggerProxy(IHello helloImpl) {

      super();

      this.helloImpl = helloImpl;

     }

     public String greeting(String who) {

      log( "starting...");

      String hello = helloImpl.greeting(who);

      log("stopping...");

      return hello;

     }

     public void log(String message)

     {

      logger.log(Level.INFO, message);

     }

    }

    客户端测试代码:

    package com.softeem.aop.staticProxy;

    public class TestStaticProxy {

           public static void main(String[] args) {

                  IHello hello = new HelloLoggerProxy(new HelloImpl());

                  hello.greeting("leno");

           }

    }

     由以上代码可以看出,客户实际需要调用的是HelloImpl类的greeting()方法,现在用HelloLoggerProxy来代理HelloImpl类,同样达到目的,同时还在方法调用的前后都做了日志记录。这就是静态代理。

    但是,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实色必须对应角一个代理角色,如果大量使用会导致类的急剧膨胀;而且,如果项目中要做日志的类有100个,每个类里面有100个方法。重复代码就太可怕了。有人说,不怕,我就一愚公。好,有天项目经理突然要求修改做日志的方式,你再看看这些方法,估计撞墙的心都有了。那怎么办?我们就改用动态代理。

    JDK1.3以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行商业方法,在商业方法被调用的同时,执行处理器会被自动调用。

    动态代理类:

    package com.softeem.aop.dynamicProxy;

    import java.lang.reflect.InvocationHandler;

    import java.lang.reflect.Method;

    import java.lang.reflect.Proxy;

    import java.util.logging.Level;

    import java.util.logging.Logger;

    public class DynamicLoggerProxy implements InvocationHandler {

           private Logger logger = Logger.getLogger(this.getClass().getName());

           private Object delegate;

           @SuppressWarnings("unchecked")

         public Object bind(Object delegate)

           {

                  this.delegate = delegate;

                  Class cls = delegate.getClass();

                  return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);

           }

           public Object invoke(Object o, Method method, Object[] args)

                         throws Throwable {

                  log( "starting...");

                  Object obj = method.invoke(delegate, args);

                  log("stopping...");

                  return null;

           }

           public void log(String message)

           {

                  logger.log(Level.INFO, message);

           }

    }

    客户端测试代码:

    package com.softeem.aop.dynamicProxy;

    public class TestDynamicProxy {

           public static void main(String[] args) {

                  IHello hello = (IHello) new DynamicLoggerProxy().bind(new HelloImpl());

                  hello.greeting("leno");

           }

    }

    大家看到,一个动态代理类就代替了无数个静态代理类。一劳永逸。这里涉及到一些java反射的知识,我会在以后单独讲述。

    java的动态代理非常实用和强大,可它有一个前提,需要我们的处理业务逻辑的类必须至少实现一个接口,虽然面向接口编程是

    需要提倡的,但如果我们有些现存的类就是没有实现接口,那如何代理呢?这就需要CGLIB的帮助了。继续改进我们的代码:

    没有实现任何接口的类:

    package com.softeem.aop.cglibProxy;

    public class Hello{

           public void greeting(String who) {

                  System.out.println("hello,"+who);

           }

    }

    CGLIB代理类:

    package com.softeem.aop.cglibProxy;

    import java.lang.reflect.Method;

    import java.util.logging.Level;

    import java.util.logging.Logger;

    import net.sf.cglib.proxy.Enhancer;

    import net.sf.cglib.proxy.MethodInterceptor;

    import net.sf.cglib.proxy.MethodProxy;

    public class CGLIBLoggerProxy implements MethodInterceptor {

           private final Logger logger = Logger.getLogger(this.getClass().getName());

           public Object bind(Object delegate)

           {

                  Enhancer enhancer = new Enhancer();

                  enhancer.setCallback(this);

                  enhancer.setSuperclass(delegate.getClass());

                  return enhancer.create();

           }

           public Object intercept(Object o, Method method, Object[] args,

                         MethodProxy proxy) throws Throwable {

                  log( "starting...");

                  proxy.invokeSuper(o, args);

                  log("stopping...");

                  return null;

           }

           public void log(String message)

           {

                  logger.log(Level.INFO,message);

           }

    }

    客户端测试代码:

    package com.softeem.aop.cglibProxy;

    public class TestCGLIBProxy {

           public static void main(String[] args) {

                  Hello hello = (Hello) new CGLIBLoggerProxy().bind(new Hello());

                  hello.greeting("leno");

           }

    }

    好了,有了动态代理和CGLIB,那我们就可以给任何实际的类提供代理了。从而可以在我们的代理类中加入一些与业务逻辑无关的系统级的功能服务,如:日志记录,事务处理,安全管理等。而且不会影响到我们现有的系统。看起来似乎很完美了。但是且慢,如果我们的应用中有些需要这些系统级的功能服务,而有些又不需要呢?如果把代码写死了显然达不到我们的要求。怎么办?这时候就要用到一个非常重要的思想:用配置代替编码。http://zhaoshg.iteye.com/blog/724202

    这里就开始运用SPRING的IOC配置了。我们通过SPRING的一个例子看SPRING怎么样通过IOC将JAVA的代理机制变成SPRING的AOP。http://zhaoshg.iteye.com/blog/724130

分享到:
评论

相关推荐

    JAVA Spring AOP面向切面编程笔记

    JAVA Spring AOP面向切面编程笔记

    Java Spring AOP 面向切面编程的4种实现

    Spring AOP (面向切面编程框架): Spring框架内建了支持动态代理的功能,使用@AspectJ注解可以轻松地创建AOP代理。Spring AOP既支持JDK动态代理也支持CGLIB,会根据目标类是否实现了接口选择合适的底层技术。 Guice ...

    Spring面向切面编程AOP

    面向切面编程(AOP,Aspect Oriented Programming)是Spring框架中的一个重要特性,它提供了一种模块化和声明式的方式来处理程序中的横切关注点,如日志、事务管理、安全控制等。AOP的核心概念包括切面、通知、连接...

    Spring-aop面向切面编程实例

    面向切面编程(Aspect-Oriented Programming,AOP)是Spring框架的核心特性之一,它提供了一种优雅的方式来处理系统的横切关注点,如日志、事务管理、性能监控和权限控制等。在Spring中,AOP主要通过代理模式实现,...

    Spring AOP面向切面三种实现

    在IT行业中,Spring框架是Java企业级应用开发的首选,其强大的功能之一就是AOP(面向切面编程)。本文将详细解析Spring AOP的三种实现方式,帮助你深入理解这一重要概念。 首先,理解AOP的基本概念至关重要。AOP是...

    Spring AOP面向切面编程实现原理方法详解

    Spring AOP面向切面编程实现原理方法详解 面向切面编程(AOP)是Spring框架中的一个重要内容,通过预编译方式和运行期动态代理实现,在不修改源代码的情况下,给程序动态统一添加功能的一种技术。AOP可以对业务逻辑...

    AOP面向切面编程总结

    ### AOP面向切面编程详解 #### 一、AOP概览 AOP(Aspect-Oriented Programming,面向切面编程)是一种编程思想和技术,它作为OOP(面向对象编程)的一种补充,主要解决了OOP在处理横切关注点方面的不足。在传统的...

    Spring4AOP 面向切面编程实例之方法拦截

    Spring4AOP 面向切面编程实例之方法拦截实例 一下利用Spring4的最后一个版本Spring4.3.9,实现简单的方法拦截实例。 Eclipse 建立java工程,导入必要的jar包,工程目录如下:

    SpringAop面向切片

    **Spring AOP 面向切面编程详解** 在Java世界中,Spring框架以其强大的功能和易用性闻名,其中一个核心特性就是面向切面编程(Aspect-Oriented Programming,简称AOP)。AOP是为了解决传统面向对象编程中横切关注点...

    SpringAOP切面编程依赖jar包.rar

    学习Spring开发的AOP面向切面编程时所需要的jar包,包括com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

    spring AOP切面编程

    Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它扩展了传统的面向对象编程,使得开发者可以方便地实现横切关注点,如日志、事务管理、性能监控等。在Spring中,AOP通过代理...

    spring aop 自定义切面示例

    在Spring AOP(面向切面编程)中,自定义切面是实现业务逻辑解耦、增强代码可维护性的重要手段。AspectJ是一个强大的面向切面的编程库,它提供了与Spring AOP集成的能力,使我们可以编写更为灵活和模块化的代码。...

    Spring Aop面向切面的java代码

    Spring AOP,全称Spring面向切面编程,是Spring框架中的一个重要组成部分,它提供了一种在不修改原有代码的情况下,对程序进行功能增强的技术。面向切面编程(Aspect Oriented Programming,AOP)的核心思想是将关注...

    spring4 AOP 面向切面编程@Aspect

    在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从业务逻辑中分离出来,比如日志记录、事务管理、权限检查等。`@Aspect`是Spring AOP的核心注解,用于定义一个切面。下面我们将详细...

    spring的aop切面编程实例

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许我们在不修改源代码的情况下对应用程序的行为进行统一管理和控制。在本实例中,我们将深入探讨如何使用AspectJ技术和XML配置来实现AOP。 首先,了解...

    AOP_使用spring框架进行面向切面编程

    面向切面编程(AOP)是一种编程范式,它旨在减少代码中的重复部分,特别是那些与核心业务逻辑无关但又必须处理的交叉关注点,如日志、事务管理、安全控制等。Spring框架是Java领域中实现AOP的常用工具,它通过提供...

    Chapter 6_ 使用Spring进行面向切面编程(AOP)

    面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。 除了类(classes)以外,AOP提供了 切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。

    面向切面编程

    ### 面向切面编程(AOP) 面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在提高模块化程度,通过将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,使得代码更加清晰、...

    spring-AOP面向切面编程所需jar包.zip

    该压缩包包含--学习笔记(05):轻松搞定Spring全家桶(初识篇)-面向切片编程AOP:--系列博客中新需要的三个jar包。包括spring-aspects-5.2.7.RELEASE.jar和spring-aop-5.2.7.RELEASE.jar和...

    16.2 Spring框架-AOP面向切面编程

    面向切面编程(AOP,Aspect Oriented Programming)是Spring框架中的一个重要组成部分,它提供了一种模块化和声明式的方式来处理程序中的横切关注点,如日志、事务管理、性能监控等。在传统的OOP(面向对象编程)中...

Global site tag (gtag.js) - Google Analytics