首页编程java编程java代理是什么东西?java中的代理是什么意思

java代理是什么东西?java中的代理是什么意思

编程之家 2023-10-13 91次浏览

这篇文章给大家聊聊关于java代理是什么东西,以及java中的代理是什么意思对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

java代理是什么东西?java中的代理是什么意思

java中的代理是什么意思

代理模式在设计模式中的定义就是:为其他对象提供一种代理以控制对这个对象的访问。说白了就是,在一些情况下客户不想或者不能直接引用一个对象,而代理对象可以在客户和目标对象之间起到中介作用,去掉客户不能看到的内容和服务或者增添客户需要的额外服务。

java动态代理是什么

import java.lang.reflect.Proxy;

A.创建一个实现接口InvocationHandler的类,他必须实现invoke方法

java代理是什么东西?java中的代理是什么意思

B.创建被代理的类以及接口。

C.通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)创建一个代理

D.通过代理调用方法。

java代理是什么东西?java中的代理是什么意思

java动态代理:是在运行是生成的class对象,在生成时必须提供一组或一个interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当做这些interface中的任何一个来用,当然,这个DynamicProxy其实就是一个Proxy,他不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。因此,DynamicProxy必须实现InvocationHandler接口。

5)一个动态代理了和一个InvocationHandler实现关联的。每一个动态代理实例的调用都要通过InvocationHandler接口的handler(调用处理器)来调用,动态代理不做任何执行操作,只是在创建动态代理时,把要实现的接口和handler关联,动态代理要帮助被代理执行的任务,要转交给handler来执行。其实就是调用invoke方法。

Java代理的作用和实现

JDK动态代理

动态代理的核心其实就是代理对象的生成,即 Proxy.newProxyInstance(classLoader, proxyInterface, handler)。

让我们进入newProxyInstance方法观摩下,核心代码其实就三行。

这个方法需要三个参数:

ClassLoader,用于加载代理类的 Loader类,通常这个 Loader和被代理的类是同一个 Loader类。

Interfaces,是要被代理的那些那些接口。

InvocationHandler,就是用于执行除了被代理接口中方法之外的用户自定义的操作,也是用户需要代理的最终目的。用户调用目标方法都被代理到 InvocationHandler类中定义的唯一方法 invoke中。

//获取代理类 Class cl= getProxyClass(loader, interfaces);

//获取带有InvocationHandler参数的构造方法 Constructor cons= cl.getConstructor(constructorParams);

//把handler传入构造方法生成实例 return(Object) cons.newInstance(new Object[]{ h});

一个典型的动态代理创建对象过程可分为以下四个步骤:

1、通过实现InvocationHandler接口创建调用处理器

IvocationHandler handler= new InvocationHandlerImpl(...);

2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类

Class clazz= Proxy.getProxyClass(classLoader,new Class[]{...});

3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型

Constructor constructor= clazz.getConstructor(new Class[]{InvocationHandler.class});

4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入

Interface Proxy=(Interface)constructor.newInstance(new Object[](handler));

为了简化对象创建过程,Proxy类中的newProxyInstance方法封装了2~4,只需两步即可完成代理对象的创建。

Subject proxySubject=(Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),

new Class[]{Subject.class}, new InvocationHandlerImpl(real));

生成的proxySubject继承Proxy类实现Subject接口。实现的Subject的方法实际是调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的方法(Object result=method.invoke(proxied,args));

重点Proxy.newProxyInstance,源码分析,会在其他文档中单独总结记录。类Proxy的getProxyClass方法调用ProxyGenerator的 generateProxyClass方法产生ProxySubject.class的二进制数据。

创建代理对象时序图

请点击输入图片描述

获取代理类

getProxyClass(loader, interfaces)方法用于获取代理类,它主要做了三件事情:

在当前类加载器的缓存里搜索是否有代理类,没有则生成代理类并缓存在本地JVM里。

//缓存的key使用接口名称生成的List Object key= Arrays.asList(interfaceNames);

synchronized(cache){

do{

Object value= cache.get(key);

//缓存里保存了代理类的引用 if(value instanceof Reference){

proxyClass=(Class)((Reference) value).get();

}

if(proxyClass!= null){

//代理类已经存在则返回

return proxyClass;

} else if(value== pendingGenerationMarker){

//如果代理类正在产生,则等待

try{

cache.wait();

} catch(InterruptedException e){

}

continue;

} else{

//没有代理类,则标记代理准备生成

cache.put(key, pendingGenerationMarker);

break;

}

} while(true);

}

生成并加载代理类

代理类的生成主要是以下这两行代码:

//生成代理类的字节码文件并保存到硬盘中(默认不保存到硬盘) proxyClassFile= ProxyGenerator.generateProxyClass(proxyName, interfaces);

//使用类加载器将字节码加载到内存中 proxyClass= defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);

代理类的生成过程

ProxyGenerator.generateProxyClass()方法属于sun.misc包下,Oracle并没有提供源代码,但是我们可以使用

JD-GUI这样的反编译软件打开jre\lib\rt.jar来一探究竟,以下是其核心代码的分析。

//添加接口中定义的方法,此时方法体为空 for(int i= 0; i< this.interfaces.length; i++){

localObject1= this.interfaces[i].getMethods();

for(int k= 0; k< localObject1.length; k++){

addProxyMethod(localObject1[k], this.interfaces[i]);

}

}

//添加一个带有InvocationHandler的构造方法 MethodInfo localMethodInfo= new MethodInfo("<init>","(Ljava/lang/reflect/InvocationHandler;)V", 1);

//循环生成方法体代码(省略)//方法体里生成调用InvocationHandler的invoke方法代码。(此处有所省略) this.cp.getInterfaceMethodRef("InvocationHandler","invoke","Object; Method; Object;")

//将生成的字节码,写入硬盘,前面有个if判断,默认情况下不保存到硬盘。 localFileOutputStream= new FileOutputStream(ProxyGenerator.access$000(this.val$name)+".class");

localFileOutputStream.write(this.val$classFile);

生成的代理类源码

那么通过以上分析,我们可以推出动态代理为我们生成了一个这样的代理类。把方法doSomeThing的方法体修改为调用LogInvocationHandler的invoke方法。

public class ProxyBusiness extends Proxy implements IBusiness, IBusiness2{

private LogInvocationHandler h;

@Override public void doSomeThing2(){

try{

Method m=(h.target).getClass().getMethod("doSomeThing2",null);

h.invoke(this, m, null);

} catch(Throwable e){

//异常处理(略)

}

}

@Override public boolean doSomeThing(){

try{

Method m=(h.target).getClass().getMethod("doSomeThing", null);

return(Boolean) h.invoke(this, m, null);

} catch(Throwable e){

//异常处理(略)

}

return false;

}

public ProxyBusiness(LogInvocationHandler h){

this.h= h;

}

测试代理的代码如下:

//测试public static void main(String[] args){

//构建AOP的Advice

LogInvocationHandler handler= new LogInvocationHandler(new Business());

new ProxyBusiness(handler).doSomeThing();

new ProxyBusiness(handler).doSomeThing2();

}

下面看一个自定义代理的实现。

被代理类接口

public interface Subject{

public void doSomething();

}

被代理类

//目标对象public class RealSubject implements Subject{ public void doSomething(){

System.out.println("call doSomething()");

}

}

调用处理器(切面)

public class ProxyHandler implements InvocationHandler{

private Object proxied;

public ProxyHandler( Object proxied){

this.proxied= proxied;

}

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

//在转调具体目标对象之前,可以执行一些功能处理System.out.println("doSomething before");//转调具体目标对象的方法

return method.invoke( proxied, args);

//在转调具体目标对象之后,可以执行一些功能处理System.out.println("doSomething after");

}

}

测试我们的代理实现

public class DynamicProxy{

public static void main( String args[]){

RealSubject real= new RealSubject();

Subject proxySubject=(Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),

new Class[]{Subject.class}, new ProxyHandler(real));

proxySubject.doSomething();//write proxySubject class binary data to file

createProxyClassFile();

}

public static void createProxyClassFile(){

String name="ProxySubject";

byte[] data= ProxyGenerator.generateProxyClass( name, new Class[]{ Subject.class});

try{

FileOutputStream out= new FileOutputStream( name+".class");

out.write( data);

out.close();

}catch( Exception e){

e.printStackTrace();

}

}

}

运行结果:

doSomething beforecall doSomething()doSomething after

Proxy接口

Proxy的主要静态变量

//映射表:用于维护类装载器对象到其对应的代理类缓存private static Map loaderToCache= new WeakHashMap();//标记:用于标记一个动态代理类正在被创建中private static Object pendingGenerationMarker= new Object();//同步表:记录已经被创建的动态代理类类型,主要被方法 isProxyClass进行相关的判断private static Map proxyClasses= Collections.synchronizedMap(new WeakHashMap());//关联的调用处理器引用protected InvocationHandler h;

Proxy的构造方法//由于 Proxy内部从不直接调用构造函数,所以 private类型意味着禁止任何调用private Proxy(){}//由于 Proxy内部从不直接调用构造函数,所以 protected意味着只有子类可以调用protected Proxy(InvocationHandler h){this.h= h;}

ProxySubject源码

创建的代理类 ProxySubject.class

import java.lang.reflect.*;

public final class ProxySubject extends Proxy implements Subject{

private static Method m1;

private static Method m0;

private static Method m3;

private static Method m2;

public ProxySubject(InvocationHandler invocationhandler){

super(invocationhandler);

}

public final boolean equals(Object obj){

try{

return((Boolean)super.h.invoke(this, m1, new Object[]{

obj

})).booleanValue();

}catch(Error _ex){

}catch(Throwable throwable){

throw new UndeclaredThrowableException(throwable);

}

}

public final int hashCode(){

try{

return((Integer)super.h.invoke(this, m0, null)).intValue();

}catch(Error _ex){

}catch(Throwable throwable){

throw new UndeclaredThrowableException(throwable);

}

}

/*关键部分*/

public final void doSomething(){

try{

// Proxy类中protected InvocationHandler h;关联的调用处理器引用

super.h.invoke(this, m3, null);

return;

}catch(Error _ex){

}catch(Throwable throwable){

throw new UndeclaredThrowableException(throwable);

}

}

public final String toString(){

try{

return(String)super.h.invoke(this, m2, null);

} catch(Error _ex){

} catch(Throwable throwable){

throw new UndeclaredThrowableException(throwable);

}

}

static{

try{

m1= Class.forName("java.lang.Object").getMethod("equals", new Class[]{

Class.forName("java.lang.Object")

});

m0= Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);

m3= Class.forName("Subject").getMethod("doSomething", new Class[0]);

m2= Class.forName("java.lang.Object").getMethod("toString", new Class[0]);

}catch(NoSuchMethodException nosuchmethodexception){

throw new NoSuchMethodError(nosuchmethodexception.getMessage());

}catch(ClassNotFoundException classnotfoundexception){

throw new NoClassDefFoundError(classnotfoundexception.getMessage());

}

}

}

CGLib动态代理

动态字节码生成。使用动态字节码生成技术实现AOP原理是在运行期间目标字节码加载后,生成目标类的子类,将切面逻辑加入到子类中,所以使用Cglib实现AOP不需要基于接口。

public static void main(String[] args){

byteCodeGe();

}

public static void byteCodeGe(){

//创建一个织入器

Enhancer enhancer= new Enhancer();

//设置父类

enhancer.setSuperclass(Business.class);

//设置需要织入的逻辑

enhancer.setCallback(new LogIntercept());

//使用织入器创建子类

IBusiness2 newBusiness=(IBusiness2) enhancer.create();

newBusiness.doSomeThing2();

}

/**

*记录日志

*/ public static class LogIntercept implements MethodInterceptor{

@Override

public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable{

//执行原有逻辑,注意这里是invokeSuper

Object rev= proxy.invokeSuper(target, args);

//执行织入的日志

if(method.getName().equals("doSomeThing2")){

System.out.println("记录日志");

}

return rev;

}

}

END,本文到此结束,如果可以帮助到大家,还望关注本站哦!

零基础自学java看什么书,零基础的人学java,看哪些书。。求推荐几本书籍 accp和java有什么区别 java培训要学习哪些内容