当前位置:首页 > CN2资讯 > 正文内容

Java 代理java 静态代理

15小时前CN2资讯


当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象。

按照代理对象的创建时期不同,可以分为两种:

静态代理:事先写好代理对象类,在程序发布前就已经存在了;

动态代理:应用程序发布后,通过动态创建代理对象。

静态代理其实就是一个典型的代理模式实现,在代理类中包装一个被代理对象,然后影响被代理对象的行为,比较简单,代码就不放了。

其中动态代理又可分为:JDK动态代理和CGLIB代理。

 

1.JDK动态代理

此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。

代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。

JDK动态代理只能针对实现了接口的类生成代理。

2.CGLIB代理

CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,

主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。

JDK动态代理和CGLIB代理生成的区别

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。

CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。

因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

PS:final 所修饰的数据具有“终态”的特征,表示“最终的”意思:

final 修饰的类不能被继承。

final 修饰的方法不能被子类重写。

final 修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次。

final 修饰的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有 一次赋值的机会,而且只能在构造方法中显式赋值,然后才能使用。

final 修饰的局部变量可以只声明不赋值,然后再进行一次性的赋值。

 

JDK代理:



import java.lang.reflect.*;


public class Main{
public static void main(String[] args) {
// 我们要代理的真实对象
Subject realSubject = new RealSubject();
// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象调用方法的
InvocationHandler handler = new DynamicProxy(realSubject);
/*
* 通过Proxy的newProxyInstance方法来动态创建我们的代理对象,我们来看看其三个参数<br/>
* 参数一:我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象<br/>
* 参数二:我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了<br/>
* 参数三:我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Subject proxyInstance = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),
RealSubject.class.getInterfaces(),
handler);

System.out.println(proxyInstance.getClass().getName());
proxyInstance.visit();
}
}

interface Subject {
public void visit();
}

class RealSubject implements Subject {

@Override
public void visit() {
System.out.println("I am 'RealSubject',I am the execution method");
}

}

class DynamicProxy implements InvocationHandler {

// 我们要代理的真实对象(委托对象)
private Object subject;

// 构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object obj){
this.subject = obj;
}

@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable {
// 在代理真实对象操作前 我们可以添加一些自己的操作
System.out.println("before proxy invoke");

// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);

// 在代理真实对象操作后 我们也可以添加一些自己的操作
System.out.println("after proxy invoke");
return null;
}
}



com.company.$Proxy0
before proxy invoke
I am 'RealSubject',I am the execution method
after proxy invoke


 CGLib代理:



package com.company;


import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.MethodInterceptor;

import java.lang.reflect.Method;

public class Main{
public static void main(String[] args) {
CglibDynamicProxy cglib = new CglibDynamicProxy();
CglibRealSubject realSubject = (CglibRealSubject) cglib.getProxyInstance(new CglibRealSubject());
realSubject.visit();
}
}

class CglibRealSubject{
public void visit() {
System.out.println("I am 'RealSubject',I am the execution method");
}
}

class CglibDynamicProxy implements MethodInterceptor {
private Object target;

/**
* 创建代理对象
* @param target 被代理的对象
* @return
*/
public Object getProxyInstance(Object target){
this.target = target;
// 声明增强类实例
Enhancer enhancer = new Enhancer();
// 设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
enhancer.setSuperclass(this.target.getClass());
// 设置要代理的拦截器,回调函数,即一个方法拦截 new MethodInterceptor()
enhancer.setCallback(this);
// 创建代理对象 实例
return enhancer.create();
}

@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 在代理真实对象操作前 我们可以添加一些自己的操作
System.out.println("前置代理,增强处理");

proxy.invokeSuper(obj, args);

// 在代理真实对象操作后 我们也可以添加一些自己的操作
System.out.println("后置代理,增强处理");
return null;
}
}



前置代理,增强处理
I am 'RealSubject',I am the execution method
后置代理,增强处理


    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/24121.html

    标签: Java代理
    分享给朋友:

    “Java 代理java 静态代理” 的相关文章

    BT下载机的使用技巧与软件下载推荐

    在数字时代,文件共享变得越来越普遍,BT下载机作为一种基于BitTorrent协议的P2P(Peer-to-Peer)文件共享工具,扮演着重要的角色。我记得第一次接触BT下载机时,发现它的操作不仅简单,还能快速下载大型文件,这让我对它产生了浓厚的兴趣。BT下载机允许用户通过种子文件(.torrent...

    优化RackNerd DC2机房 IP使用体验与性能评测

    我最近对RackNerd的DC2机房产生了越来越多的兴趣,特别是位于美国洛杉矶的这座机房。它被誉为RackNerd中中国国内访问速度较快的机房之一,吸引了很多需求高效网络连接的用户。这座机房的地理位置确实蛮不错,靠近美西主干线,对于需要与国内建立连接的网站和应用来说,能带来相对更快的访问速度。 对于...

    选择台湾VPS的优势与实用技巧分析

    在当今互联网迅速发展的时代,虚拟专用服务器(VPS)成为了众多企业和个人不二的选择。台湾VPS作为一个相对新兴的产品,凭借自己独特的地理位置和优异的技术性能,逐渐在市场上占据了一席之地。身为个人或企业,在选择服务器时,了解台湾VPS的基本概念及其优势无疑是一个明智的开始。 什么是VPS? VPS,即...

    如何选择便宜的海外服务器来提升业务效率

    什么是海外服务器 海外服务器简单来说,就是在国外数据中心托管的服务器。那些需要在国外提供服务和访问的企业或者个人,会选择这种类型的服务器。比起本地服务器,海外服务器往往能提供更好的网络速度和稳定性,尤其是对某些特定的地区来说。如果你有过在网上购物或者访问国际网站的经历,或许你会发现他们的响应速度比一...

    日本节点的重要性与旅行体验优化指南

    日本节点的定义与重要性 在数字化飞速发展的今天,网络成为了沟通和信息流通的主要渠道。这里提到的“节点”,其实是指网络中数据传输的关键环节,可以理解为互联网的一个重要接点。每一个节点都承担着流量的传输与分发,确保数据能够迅速而高效地在全球范围内流动。想象一下,网络就像一张巨大的蜘蛛网,各个节点犹如网中...

    Linode vs Vultr:选择最佳云服务提供商的指南

    Linode与Vultr概述 在这个云计算的时代,Linode和Vultr是两家备受瞩目的云服务提供商。作为一个用户,我常常在这两者之间进行比较,寻找最适合的解决方案。Linode成立于2003年,专注于为开发者提供虚拟私人服务器(VPS)。它的服务以简单和高效著称,非常适合中小型企业和开发者使用。...