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

基于Java Dynamic Proxy(面向Interface)的Spring AOP实现原理

阅读更多
Dynamic Proxy是面向接口的动态代理实现,其代理对象必须是某个接口的实现。Dynamic Proxy通过在运行期构建一个此接口的动态实现类完成对目标对象的代理(相当于在运行期动态构造一个UserDAOProxy,完成对UserDAOImp的代理任务)。而如果目标代理对象并未实现任何接口,那么Dynamic Proxy就失去了创建动态代理类的基础依据。

我们先来看传统方式下一个Proxy的实现实例。
假设我们有一个UserDAO接口及其实现类UserDAOImp:
UserDAO.java:
public interface UserDAO {
    public void saveUser(User user);
}
UserDAOImp.java:
public class UserDAOImp implements UserDAO{
    public void saveUser(User user) {
    ……
    }
}

UserDAOImp.saveUser方法中实现了针对User对象的数据库持久逻辑。
如果我们希望在UserDAOImp.saveUser方法执行前后追加一些处理过程,如启动/
提交事务,而不影响外部代码的调用逻辑,那么,增加一个Proxy类是个不错的选择:
UserDAOProxy.java
public class UserDAOProxy implements UserDAO {
  private UserDAO userDAO;
  public UserDAOProxy(UserDAO userDAO) {
    this.userDAO = userDAO;
  }
  public void saveUser(User user) {
    UserTransaction tx = null;
    try {
         tx = (UserTransaction) (
            new InitialContext().lookup("java/tx")
         );
         userDAO.saveUser(user);
         tx.commit();
     } catch (Exception ex) {
     if (null!=tx){
       try {
          tx.rollback();
       }catch(Exception e) {
       }
     }
   }
}
}

UserDAOProxy同样是UserDAO接口的实现,对于调用者而言,saveUser方法的使用完全相同,不同的是内部实现机制已经发生了一些变化――我们在UserDAOProxy中为UserDAO.saveUser方法套上了一个JTA事务管理的外壳。
上面是静态Proxy模式的一个典型实现。

现在假设系统中有20个类似的接口,针对每个接口实现一个Proxy,实在是个繁琐无味的苦力工程。
Dynamic Proxy的出现,为这个问题提供了一个更加聪明的解决方案。
我们来看看怎样通过Dynamic Proxy解决上面的问题:

public class TxHandler implements InvocationHandler {
    private Object originalObject;
    public Object bind(Object obj) {
        this.originalObject = obj;
        return Proxy.newProxyInstance(
            obj.getClass().getClassLoader(),
            obj.getClass().getInterfaces(),
            this
         );
    }
    public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
       Object result = null;
       if (!method.getName().startsWith("save")) {
        UserTransaction tx = null;
        try {
                tx = (UserTransaction) (
                     new InitialContext().lookup("java/tx")
                    );
                result = method.invoke(originalObject, args);
            
                tx.commit();
            } catch (Exception ex) {
          if (null != tx) {
              try {
                  tx.rollback();
              } catch (Exception e) {
              }
           }
         }
      } else {
           result = method.invoke(originalObject, args);
      }
      return result;
   }
}

首先注意到,上面这段代码中,并没有出现与具体应用层相关的接口或者类引用。也就是说,这个代理类适用于所有接口的实现。
其中的关键在两个部分:
1.
  return Proxy.newProxyInstance(
     obj.getClass().getClassLoader(),
     obj.getClass().getInterfaces(),
     this);

java.lang.reflect.Proxy.newProxyInstance方法根据传入的接口类型(obj.getClass().getInterfaces())动态构造一个代理类实例返回,这个代理类是JVM在内存中动态构造的动态类,它实现了传入的接口列表中所包含的所有接口。
这里也可以看出,Dynamic Proxy要求所代理的类必须是某个接口的实现(obj.getClass().getInterfaces()不可为空),否则无法为其构造响应的动态类。这也就是为什么Spring对接口实现类通过Dynamic Proxy实现AOP。

2.
   public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
      ……

       result = method.invoke(originalObject, args);
      ……
       return result;
   }

InvocationHandler.invoke方法将在被代理类的方法被调用之前触发。通过这个方法中,我们可以在被代理类方法调用的前后进行一些处理,如代码中所示,InvocationHandler.invoke方法的参数中传递了当前被调用的方法(Method),以及被
调用方法的参数。同时,我们可以通过Method.invoke方法调用被代理类的原始方法实现。这样,我们就可以在被代理类的方法调用前后大做文章。
在示例代码中,我们为所有名称以“save”开头的方法追加了JTA事务管理。

谈到这里,可以回忆一下Spring事务配置中的内容:
<property name="transactionAttributes">
   <props>
      <prop key="save*">PROPAGATION_REQUIRED</prop>
      <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
   </props>
</property>

想必大家已经猜测到Spring事务管理机制的实现原理。
是的,只需通过一个Dynamic Proxy对所有需要事务管理的Bean进行加载,并根据配置,在invoke方法中对当前调用的方法名进行判定,并为其加上合适的事务管理代码,那么就实现了Spring式的事务管理。当然,Spring中的AOP实现更为复杂和灵活,不过基本原理一致。

Spring中Dynamic Proxy AOP实现类为:
org.springframework.aop.framework.JdkDynamicAopProxy
分享到:
评论

相关推荐

    java中动态代理,springAop.pdf

    Spring AOP(面向切面编程)是Spring框架的一个重要组成部分,它利用动态代理来实现切面的注入,从而达到代码解耦和模块化的目的。 在Java中,动态代理主要有两种实现方式:JDK动态代理和CGLIB。这里我们主要讨论...

    aop的四种实现方式

    **AOP(面向切面编程)**是一种编程范式,它允许程序员定义“切面”,这些切面可以封装跨越多个对象的行为或责任。在Java世界中,AOP主要用于日志记录、事务管理、性能监控等场景,使得这些跨功能的需求能够模块化...

    AOP.pdf

    Spring AOP主要基于代理机制来实现,支持两种类型的代理: 1. **静态代理(Static Proxy)** 2. **动态代理(Dynamic Proxy)** ##### 3.1 静态代理 在静态代理中,代理类和目标类都需要实现相同的接口。这种方式...

    Java ee 企业应用开发:第7章 在Spring中管理事务.ppt

    Spring框架提供了强大的事务管理能力,通过面向切面编程(AOP)实现。AOP允许开发者将横切关注点,如日志、事务控制、安全性等,从核心业务逻辑中解耦出来。 ### 7.1 AOP简介 AOP(Aspect Oriented Programming)...

    Spring的静态代理和动态代理

    在Java编程领域,Spring框架是不可或缺的一部分,尤其在企业级应用开发中,它提供了许多强大的功能,其中之一就是AOP(面向切面编程)。本篇我们将深入探讨Spring中的静态代理和动态代理,这两种代理模式在实际开发...

    Java-Dynamic-Proxy:动态代理实现

    在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类用于创建动态代理实例,而 `InvocationHandler` 接口则定义了当调用代理对象的方法时应...

    spring框架各jar包详解

    CGLIB 用来生成动态代理类(dynamic proxy classes),供核心 DI 和 AOP 实现之用。由于大量 Spring 功能的实现都要用到 CGLIB,因此你的应用几乎总需包含 CGLIB。 coscos.jar COS 代表 com.oreilly.servlet,是个...

    Spring开发指南

    Spring AOP部分会介绍AOP的基本概念、Spring中的AOP实现以及与动态代理(Dynamic Proxy)和CGLib等技术的结合使用。 DAO(Data Access Object)支持是Spring提供的数据访问抽象,它封装了数据访问的细节,使得...

    Java中的代理模式Demo

    代理模式在实际开发中的应用广泛,如AOP(面向切面编程)框架Spring的AOP代理,以及在数据库操作中实现缓存、事务管理等场景。通过代理模式,我们可以将关注点分离,增强代码的可扩展性和灵活性。同时,动态代理的...

    浅谈java代理机制 .txt

    Java代理机制是软件开发中一个重要的技术手段,特别是在实现面向切面编程、增强类的功能等方面有着广泛的应用。通过理解并掌握Java代理机制,开发者可以更加灵活地应对复杂的业务需求,提高代码的可扩展性和可维护性...

    Java两种代理模式案例

    动态代理通常用于AOP(面向切面编程)框架,如Spring AOP,它可以更加灵活地在运行时添加增强功能,而无需修改目标类源码。 ### 3. `ProxyDemo`案例 在`ProxyDemo`案例中,可能会包含上述静态代理和动态代理的示例...

    JavaEE proxy简单代理示例

    在JavaEE开发中,代理模式是一种常见的设计模式,它允许我们为一个对象提供一个替代...在实际项目中,我们经常会结合Spring框架中的AOP(面向切面编程)来实现更复杂的代理逻辑,从而实现业务代码的解耦和可维护性。

    静态代理动态代理测试,模拟jdk实现动态代理

    在实际应用中,动态代理常用于AOP(面向切面编程)场景,例如Spring框架中的AOP代理就是基于JDK动态代理或者CGLIB来实现的,可以在方法调用前、后或异常时插入自定义的行为。 通过上述的静态代理和动态代理的讲解,...

    内容综述2

    Spring对Java语言特性的运用体现在多方面,比如利用Java 5引入的注解(Annotation)简化配置,通过动态代理(Dynamic Proxy)实现AOP,以及使用元编程(Metaprogramming)进行更灵活的代码生成。此外,Spring还整合...

    cglib代理资料类,静态代理动态代理

    它们在Java开发中都有广泛的应用,尤其是在AOP(面向切面编程)和框架设计中,如Spring AOP就使用了这两种代理技术。了解并熟练掌握这些代理机制,能够帮助我们更好地理解和使用Java的高级特性。

    java动态得值

    在Spring框架中,依赖注入(DI)和面向切面编程(AOP)允许我们动态配置和管理对象。通过XML配置文件或注解,我们可以动态控制对象的创建和行为,实现灵活的业务逻辑。 综上所述,Java的动态得值涉及多个方面,包括...

    代理模式-静态动态代理-jdk动态代理-cglib动态代理

    在Spring框架中,代理模式被广泛应用,例如AOP(面向切面编程)就是通过代理模式实现的。Spring支持JDK动态代理和CGLIB动态代理,根据目标类是否实现了接口来选择合适的代理方式。 总结来说,代理模式是软件设计中...

    agent:Java代理

    在上述例子中,`DynamicProxy`实现了`InvocationHandler`接口,`invoke`方法是代理逻辑的核心。`Proxy.newProxyInstance()`用于创建动态代理对象,它可以调用任何接口的方法。 **JDK动态代理与CGLIB代理** 当目标类...

    反射-动态代理-注解

    这三者在实际开发中结合使用,可以实现很多强大的功能,例如Spring AOP(面向切面编程)就是利用动态代理和注解实现的。通过注解标记切点,再利用反射和动态代理在运行时生成代理对象,实现方法拦截,从而实现事务...

    学软件编程需必学的英语)第二学年Java方向

    2. **Technology技术**:用于实现MVC架构的技术栈,如Java、Spring MVC等。 3. **Component组件**:MVC架构中的各个组成部分。 4. **Container容器**:管理组件生命周期和依赖注入的容器,如Spring框架提供的...

Global site tag (gtag.js) - Google Analytics