Java Web之动态代理

简介: 动态代理通俗解释:A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做,可以先声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口, 对外界来说B'应该也有c方法,可当真正调用它的时候, 它会去执行与它关联InvocationHandler的invoke()方法, 在这个方法里面你可以做很多事情。

动态代理通俗解释:

A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做,可以先声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口, 对外界来说B'应该也有c方法,可当真正调用它的时候, 它会去执行与它关联InvocationHandler的invoke()方法, 在这个方法里面你可以做很多事情。

Java怎样实现动态代理呢

第一步,我们要有一个接口,还要有一个接口的实现类,而这个实现类就是我们要代理的类。

public interface Subject
{
    public void request();
}

public class RealSubject implements Subject
{
    public void request()
    {
        System.out.println("From real subject!");
    }

}

第二步,我们要自己写一个代理类,它的特点是实现了InvocationHandler接口, 因为代理类的实例在调用实现类的方法的时候,不是去调用真正的实现类的这个方法, 而是调用代理类的invoke()方法,在这个方法中才调用真正的实现类的方法。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 该代理类的内部属性是Object类型,实际使用的时候通过该类的构造方法传递进来一个对象
 * 此外,该类还实现了invoke方法,该方法中的method.invoke其实就是调用被代理对象的将要
 * 执行的方法,方法参数是sub,表示该方法从属于sub,通过动态代理类,我们可以在执行真实对象的方法前后
 * 加入自己的一些额外方法,这里在方法调用前后打印一句话。
 *
 */

public class DynamicSubject implements InvocationHandler
{
    private Object sub;
    
    public DynamicSubject(Object obj)
    {
        this.sub = obj;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
    {
        System.out.println("before calling: " + method);
        
        method.invoke(sub, args);
        
        System.out.println(args == null);
        
        System.out.println("after calling: " + method);
        
        return null;
    }   
    
}

上述方法体中method.invoke(owner, args)的解释:执行该method.invoke方法的参数是执行这个方法的对象owner,参数数组args,可以这么理解:owner对象中带有参数args的method方法。返回值是Object,也就是该方法的返回值。

第三步,客户端要用代理类的实例去调用实现类的方法。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client
{
    public static void main(String[] args)
    {
        RealSubject realSubject = new RealSubject();

        InvocationHandler handler = new DynamicSubject(realSubject);

        Class<?> classType = handler.getClass();

        // newProxyInstance()动态生成一个类并加载到内存
        // 加载到内存要使用加载器,第一个参数是一个类加载器
        Subject subject = (Subject) Proxy.newProxyInstance(classType
                .getClassLoader(), realSubject.getClass().getInterfaces(),
                handler);

        subject.request();

        System.out.println(subject.getClass());

    }

}

对第三步的解释

主要是以下代码:

Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

该方法主要做了如下工作:

  • 根据参数loader和interfaces调用方法 getProxyClass(loader, interfaces) 创建代理类$Proxy0,该代理类实现了预先定义的接口(如上面的Subject),并继承了Proxy类。
public final class $Proxy0 extends Proxy implements Subject
  • 实例化$Proxy0(创建代理对象)并在构造方法中把 InvocationHandler(这里handler 是它的实例)传过去

  • $Proxy0调用父类Proxy的构造器,为InvocationHandler 赋值:

public $Proxy0(InvocationHandler invocationhandler)
{
  super(invocationhandler);
}
========================================================
class Proxy
{
   protected InvocationHandler h;
   protected Proxy(InvocationHandler h) 
   {
         this.h = h;
   }
}
  • 将这个$Proxy0类强制转型成接口类型,当执行接口中的方法时(如上文强转成Subject后调用request()方法),就调用了$Proxy0类中实现的接口方法,在该方法中会调用父类Proxy中的invoke()方法,即InvocationHandler.invoke(),达到做一些其他工作的效果。
public final void request()
{
  try
  {
      //m是通过反射得到的方法名 Method类型
      super.h.invoke(this, m, null);
      return;
  }
  catch (Error e)
  {

  }
  catch (Throwable throwable)
  {
    throw new UndeclaredThrowableException(throwable);
  }
}
目录
相关文章
|
19天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
1月前
|
Java Maven Spring
Java Web 应用中,资源文件的位置和加载方式
在Java Web应用中,资源文件如配置文件、静态文件等通常放置在特定目录下,如WEB-INF或classes。通过类加载器或Servlet上下文路径可实现资源的加载与访问。正确管理资源位置与加载方式对应用的稳定性和可维护性至关重要。
53 6
|
1月前
|
存储 安全 搜索推荐
理解Session和Cookie:Java Web开发中的用户状态管理
理解Session和Cookie:Java Web开发中的用户状态管理
69 4
|
28天前
|
Java
JAVA 静态代理 & 动态代理
【11月更文挑战第14天】静态代理是一种简单的代理模式实现,其中代理类和被代理类的关系在编译时已确定。代理类实现与被代理类相同的接口,并持有被代理类的实例,通过调用其方法实现功能增强。优点包括代码结构清晰,易于理解和实现;缺点是对于多个被代理类,需为每个类编写相应的代理类,导致代码量大增,维护成本高。动态代理则在运行时动态生成代理类,更加灵活,减少了代码冗余,但可能引入性能损耗和兼容性问题。
|
2月前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
32 0
[Java]静态代理与动态代理(基于JDK1.8)
|
1月前
|
Java 持续交付 项目管理
使用Maven进行项目管理:提高Java Web开发的效率
Maven 是一款强大的项目管理和构建自动化工具,广泛应用于Java社区。它通过依赖管理、构建生命周期管理、插件机制和多模块项目支持等功能,简化了项目的构建过程,提高了开发效率。本文将介绍Maven的核心功能及其在Java Web开发中的应用。
65 0
|
2月前
|
Java
深入理解Java动态代理
深入理解Java动态代理
91 1
WK
|
1月前
|
安全 Java 编译器
C++和Java哪个更适合开发web网站
在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
WK
83 0
|
2月前
|
前端开发 Java API
JAVA Web 服务及底层框架原理
【10月更文挑战第1天】Java Web 服务是基于 Java 编程语言用于开发分布式网络应用程序的一种技术。它通常运行在 Web 服务器上,并通过 HTTP 协议与客户端进行通信。
35 1
|
2月前
|
Java
Java代码解释静态代理和动态代理的区别
### 静态代理与动态代理简介 **静态代理**:代理类在编译时已确定,目标对象和代理对象都实现同一接口。代理类包含对目标对象的引用,并在调用方法时添加额外操作。 **动态代理**:利用Java反射机制在运行时生成代理类,更加灵活。通过`Proxy`类和`InvocationHandler`接口实现,无需提前知道接口的具体实现细节。 示例代码展示了两种代理方式的实现,静态代理需要手动创建代理对象,而动态代理通过反射机制自动创建。