Java开发纯接口的动态代理

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

相关类及接口

java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
//
方法 1: 该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler
getInvocationHandler(Object proxy)

// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class
getProxyClass(ClassLoader loader, Class[] interfaces)

// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)

// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object
newProxyInstance(ClassLoader loader, Class[] interfaces,
   
InvocationHandler h)

java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke
方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象。
//
该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象
//
第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
Object invoke(Object proxy, Method
method, Object[] args)java.lang.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java
虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy
静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,java开发培训它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class
文件中。
步骤
动态代理具体有如下四步骤:
1. 通过实现 InvocationHandler 接口创建自己的调用处理器;

2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3.
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4.
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

示例

package twenz.test;

public interface UserDao {
    public void save(String name);
}

package twenz.test;

public class UserDaoImp implements UserDao {

@Override
    public void save(String name) {
        // TODO
Auto-generated method stub
       
System.out.println(this.getClass().getName());
       
System.out.println(name);
    }
}

package twenz.test;

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

public class ProxyTest2 implements InvocationHandler {
    private UserDao
target;

public ProxyTest2(UserDao target)
    {
        this.target =
target;
    }

@Override
    public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
        // TODO Auto-generated method
stub
        //System.out.println("The object
is:"+proxy.getClass().getName());
        System.out.println("The method
is:"+method.getName());
        method.invoke(target, args);
       
return null;
    }

public static void  test(UserDao target) {
        ProxyTest2 proxy =
new ProxyTest2(target);
        UserDao user =
(UserDao)Proxy.newProxyInstance(ProxyTest2.class.getClassLoader(),
               
target.getClass().getInterfaces(), proxy);
        user.save("=");
   
}
}

通过调用”ProxyTest2.test(new
UserDaoImp());“则可以触发代理,会执行ProxyTest2的invoke函数并进而触发UserDaoImp的save函数

只对接口的代理
这个才是本文关注的重点,那就是如果我没有实现接口,只想调用UserDao的save函数该如何?下面这个代码是一个示例:

package twenz.test;

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

public class ProxyTest implements InvocationHandler {
    private
Class<UserDao> target;

public ProxyTest(Class<UserDao> target)
    {
       
this.target = target;
    }

@Override
    public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
        // TODO Auto-generated method
stub
        //System.out.println("The object
is:"+proxy.getClass().getName());
        System.out.println("The method
is:"+method.getName());
        return null;
    }

public static void  test(Class<UserDao> target) {
       
ProxyTest proxy = new ProxyTest(target);
        UserDao user =
(UserDao)Proxy.newProxyInstance(ProxyTest.class.getClassLoader(),
               
new Class<?>[]{target}, proxy);
        user.save("");
    }

public static void main(String args[])
    {
       
ProxyTest.test(UserDao.class);
    }
}

这里我们没有实现接口UserDao,但是我们却调用了接口的函数save。不过这里invoke里面其实并没有invoke代理的函数save,只是获取了save的方法名。

时间: 2024-10-11 09:42:20

Java开发纯接口的动态代理的相关文章

java开发必学知识:动态代理

目录 1. 引言 2. 代理模式及静态代理 2.1 代理模式说明 2.2 静态代理 2.3 静态代理局限性 3. 动态代理 3.1 JAVA反射机制 3.2 JDK动态代理 3.2.1 JDK动态代理 3.2.2 JDK动态代理与限制 3.4 CGLIB动态代理 4. 动态代理在Spring的应用:AOP 4.1 AOP 概念 4.2 AOP编程 4.2.1 引入aop依赖 4.2.2 定义切面.切点与通知 5. 总结 参考资料 往期文章 一句话概括:java动态代理通过反射机制,可在不修改原代

02.MyBatis在DAO层开发使用的Mapper动态代理方式

在实际开发中,Mybatis作用于DAO层,那么Service层该如何调用Mybatis Mybatis鼓励使用Mapper动态代理的方式 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体等于Dao接口实现类方法. 1.编写Mapper.xml映射文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP

Java的反射机制和动态代理

介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原生实现AOP中 的方法拦截功能.正如英文单词reflection的含义一样,使用反射API的时候就好像在看一个Java类在水中的倒影一样.知道了Java类的内部 结构之后,就可以与它进行交互,包括创建新的对象和调用对象中的方法等.这种交互方式与直接在源代码中使用的效果是相同的,但是又额外提供了运行时

java反射机制中的动态代理

java反射机制中的动态代理 动态代理模式及其使用 步骤1:定义一个接口 //接口 interface Subject{ void action(); } 步骤2:定义一个接口的实现类,也就是被代理类 //被代理类 class RealSubject implements Subject { @Override public void action() { System.out.println("我是被代理类,请执行我"); } } 步骤3:定义一个实现InvocationHandle

Java学习之:JDK动态代理与CGLIB动态代理

代理的概念:简单的理解就是通过为某一个对象创建一个代理对象,我们不直接引用原本的对象,而是由创建的代理对象来控制对原对象的引用. 动态代理:是指在程序运行时由Java反射机制动态生成,无需手动编写代码.动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类. 代理原理:代理对象内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象.同时,代理对象可以在执行真实对象操作时,附加其他的操作

Java基础之反射和动态代理

1,反射是依赖于Class对象,然后根据Class对象,去操作该类的资源的.Class对象是发射的基石! 问题1:人这类事物用什么表示?汽车这类事物用什么表示>计算机文件用什么表示?有如此多的事物该用什么表示? 答案:Person类,Car类,File类,这么多的类也是一类事物,这类事物用Class表示. 问题2:Person类的对象,我们知道代表一个具体的人.那么Class类的对象,又代表什么? 一个类,在硬盘上表示一个.class文件,JVM启动的时候,把文件加载到内存上,占用一片空间,称为

【代码篇】JBPM4.4开发流程节点(动态代理实现流程管理业务)

继之前的博客,[思想篇]工作流技术JBPM4.4开发入门(四),[思想篇]工作流技术JBPM4.4开发入门(五)本篇博客来结合代码简单说说,如何让流程来管理业务: 先来看看我们抽出来的代理类: StartAbstractJBPM:流程启动节点 package com.hjy.ssh.action; import com.hjy.ssh.beans.AbstractApply; import java.lang.reflect.Method; import java.lang.reflect.Pr

[Java]Spring AOP基础知识-动态代理

Spring AOP使用动态代理技术在运行期织入增强的代码,为了揭示Spring AOP底层的工作机理,有必要对涉及到的Java知识进行学习.Spring AOP使用了两种代理机制:一种是基于JDK的动态代理:另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理. 带有横切逻辑的实例 我们通过具体化代码实现上一节所介绍例子的性能监视横切逻辑,并通过动态代理技术对此进行改造.在调用每一个目标类方法时启动方法的性能监视,在目标类方法调

java反射机制应用之动态代理

1.静态代理类和动态代理类区别 静态代理:要求被代理类和代理类同时实现相应的一套接口:通过代理类的对象调用重写接口的方法时,实际上执行的是被代理类的同样的 方法的调用. 动态代理:在程序运行时,根据被代理类及其实现的接口,动态的创建一个代理类.当调用代理类的实现的抽象方法时,就发起对被代理类同样方法的调用. 涉及到的技术点: ①提供一个实现了InvocationHandler接口实现类,并重写其invoke()方法 ②Proxy.newProxyInstance(obj.getClass().g