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
分享到:
相关推荐
Spring AOP(面向切面编程)是Spring框架的一个重要组成部分,它利用动态代理来实现切面的注入,从而达到代码解耦和模块化的目的。 在Java中,动态代理主要有两种实现方式:JDK动态代理和CGLIB。这里我们主要讨论...
**AOP(面向切面编程)**是一种编程范式,它允许程序员定义“切面”,这些切面可以封装跨越多个对象的行为或责任。在Java世界中,AOP主要用于日志记录、事务管理、性能监控等场景,使得这些跨功能的需求能够模块化...
Spring AOP主要基于代理机制来实现,支持两种类型的代理: 1. **静态代理(Static Proxy)** 2. **动态代理(Dynamic Proxy)** ##### 3.1 静态代理 在静态代理中,代理类和目标类都需要实现相同的接口。这种方式...
Spring框架提供了强大的事务管理能力,通过面向切面编程(AOP)实现。AOP允许开发者将横切关注点,如日志、事务控制、安全性等,从核心业务逻辑中解耦出来。 ### 7.1 AOP简介 AOP(Aspect Oriented Programming)...
在Java编程领域,Spring框架是不可或缺的一部分,尤其在企业级应用开发中,它提供了许多强大的功能,其中之一就是AOP(面向切面编程)。本篇我们将深入探讨Spring中的静态代理和动态代理,这两种代理模式在实际开发...
在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类用于创建动态代理实例,而 `InvocationHandler` 接口则定义了当调用代理对象的方法时应...
CGLIB 用来生成动态代理类(dynamic proxy classes),供核心 DI 和 AOP 实现之用。由于大量 Spring 功能的实现都要用到 CGLIB,因此你的应用几乎总需包含 CGLIB。 coscos.jar COS 代表 com.oreilly.servlet,是个...
Spring AOP部分会介绍AOP的基本概念、Spring中的AOP实现以及与动态代理(Dynamic Proxy)和CGLib等技术的结合使用。 DAO(Data Access Object)支持是Spring提供的数据访问抽象,它封装了数据访问的细节,使得...
代理模式在实际开发中的应用广泛,如AOP(面向切面编程)框架Spring的AOP代理,以及在数据库操作中实现缓存、事务管理等场景。通过代理模式,我们可以将关注点分离,增强代码的可扩展性和灵活性。同时,动态代理的...
Java代理机制是软件开发中一个重要的技术手段,特别是在实现面向切面编程、增强类的功能等方面有着广泛的应用。通过理解并掌握Java代理机制,开发者可以更加灵活地应对复杂的业务需求,提高代码的可扩展性和可维护性...
动态代理通常用于AOP(面向切面编程)框架,如Spring AOP,它可以更加灵活地在运行时添加增强功能,而无需修改目标类源码。 ### 3. `ProxyDemo`案例 在`ProxyDemo`案例中,可能会包含上述静态代理和动态代理的示例...
在JavaEE开发中,代理模式是一种常见的设计模式,它允许我们为一个对象提供一个替代...在实际项目中,我们经常会结合Spring框架中的AOP(面向切面编程)来实现更复杂的代理逻辑,从而实现业务代码的解耦和可维护性。
在实际应用中,动态代理常用于AOP(面向切面编程)场景,例如Spring框架中的AOP代理就是基于JDK动态代理或者CGLIB来实现的,可以在方法调用前、后或异常时插入自定义的行为。 通过上述的静态代理和动态代理的讲解,...
Spring对Java语言特性的运用体现在多方面,比如利用Java 5引入的注解(Annotation)简化配置,通过动态代理(Dynamic Proxy)实现AOP,以及使用元编程(Metaprogramming)进行更灵活的代码生成。此外,Spring还整合...
它们在Java开发中都有广泛的应用,尤其是在AOP(面向切面编程)和框架设计中,如Spring AOP就使用了这两种代理技术。了解并熟练掌握这些代理机制,能够帮助我们更好地理解和使用Java的高级特性。
在Spring框架中,依赖注入(DI)和面向切面编程(AOP)允许我们动态配置和管理对象。通过XML配置文件或注解,我们可以动态控制对象的创建和行为,实现灵活的业务逻辑。 综上所述,Java的动态得值涉及多个方面,包括...
在Spring框架中,代理模式被广泛应用,例如AOP(面向切面编程)就是通过代理模式实现的。Spring支持JDK动态代理和CGLIB动态代理,根据目标类是否实现了接口来选择合适的代理方式。 总结来说,代理模式是软件设计中...
在上述例子中,`DynamicProxy`实现了`InvocationHandler`接口,`invoke`方法是代理逻辑的核心。`Proxy.newProxyInstance()`用于创建动态代理对象,它可以调用任何接口的方法。 **JDK动态代理与CGLIB代理** 当目标类...
这三者在实际开发中结合使用,可以实现很多强大的功能,例如Spring AOP(面向切面编程)就是利用动态代理和注解实现的。通过注解标记切点,再利用反射和动态代理在运行时生成代理对象,实现方法拦截,从而实现事务...
2. **Technology技术**:用于实现MVC架构的技术栈,如Java、Spring MVC等。 3. **Component组件**:MVC架构中的各个组成部分。 4. **Container容器**:管理组件生命周期和依赖注入的容器,如Spring框架提供的...