java动态代理(知识点扫盲)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java动态代理(知识点扫盲)相关的知识,希望对你有一定的参考价值。

动态代理就先说代理模式,然后是动态代理

代理模式中,会有代理对象,和被代理对象(目标业务对象)。代理对象会拦截对目标业务对象的访问。类似于现实中的老师和经纪人。

/*
* 老师的接口
*/
public interface drawer {
public void sing(double money);
public void draw(double money);
public void sleep();
}
/*
* 一个具体的老师:徐老师
*/
public class Xulaoshi implements drawer {
@Override
public void sing(double money) {
System.out.println("徐老师教了一首歌!");
System.out.println("徐老师赚了" + money + "RMB");
}
@Override
public void draw(double money) {
System.out.println("徐老师教了一节画画!");
System.out.println("徐老师赚了" + money + "RMB");
}
@Override
public void sleep() {
System.out.println("徐老师太累了。。。休息一会儿");
}
}

/*
* 代理类A,代理徐老师
*/
public class A implements drawer {
// 持有真实业务对象
private drawer s;

// 接收真实业务对象
public A(drawer s) {
this.s = s;
}

@Override
public void sing(double money) {
// 做一个拦截
if (money < 100000) {
System.out.println("钱太少,不去");
return;
}
System.out.println("A抽取" + money * 0.6 + "提成");
s.sing(money * 0.4);
}

@Override
public void draw(double money) {
// 做一个拦截
if (money < 500000) {
System.out.println("钱太少,加钱!");
return;
}
System.out.println("A抽取" + money * 0.6 + "提成");
s.draw(money * 0.4);
}

@Override
public void sleep() {
System.out.println("帮忙定个酒店。。。");
s.sleep();
}
}
/** 演示:代理模式
* 代理:代理对象主要用来拦截目标业务对象(被代理对象)的访问。
*  A:代理对象要持有真实业务对象。(通过构造函数接收业务对象,并用成员变量记录)
*  B:代理对象要和真实业务对象,具备相同的行为方法(实现相同接口)
*  C:代理对象拦截对真实对象的访问,可以修改访问的参数、返回值,甚至拦截访问* 代理模式与装饰模式区别
*  A:代理模式侧重与拦截,装饰模式侧重与加强
*  B:Java中自带的代理中,只能对接口进行代理。装饰只需要与被装饰类有共同父类。
*/
public class ProxyDemo01 {
public static void main(String[] args) {
// 创建被代理对象
Xulaoshi Xulaoshi = new Xulaoshi();
// 创建代理对象
A  a= new A(Xulaoshi);

// 访问方法
a.sing(500);
System.out.println("----------");
a.draw(1000000);
System.out.println("----------");
a.sleep();
}
}

下面动态代理

技术分享图片


/** 演示:动态代理
* 动态代理:在程序运行过程中产生的一个代理对象
* 在程序运行的过程中,动态在内存中生成一个类,代理需要被代理的目标对象,并且生成这个代理类的对象。
* Java如何凭空生成一个代理类,并且代理徐老师的呢?我们要查看一个API:
*  static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
*   ClassLoader loader :类加载器,一般用被代理对象的类加载器
*   Class[] interfaces : 被代理对象的接口的Class对象数组,Class<?>[] getInterfaces()  
*   InvocationHandler h : 调用处理器
*/
public class ProxyDemo02 {
public static void main(String[] args) {
// 创建被代理对象
final Xulaoshi Xulaoshi = new Xulaoshi();
// 先准备动态代理的三大参数
// 被代理类的类加载器
ClassLoader loader =Xulaoshi .getClass().getClassLoader();
// 被代理对象的接口的Class对象数组
Class<?>[] interfaces =Xulaoshi .getClass().getInterfaces();
//Xulaoshi .getClass().getInterfaces();{drawer.class}
// 调用处理器
InvocationHandler h = new InvocationHandler(){
// 当我们调用代理对象的功能时,代理对象,其实都来调用了处理器中的invoke功能
// 因此,我们需要在invoke中写拦截的逻辑!
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object proxy : 是代理对象本身
// Method method :当前正在被调用的真实方法的对象
// Object[] args : 当前正在被调用的真实方法的真实参数
String name = method.getName();
// 判断方法的名称,做出不同的拦截逻辑
if( "sing".equals(name) || "draw".equals(name)){
double money = (double) args[0];
double min = "sing".equals(name) ? 100000 : 500000;
if (money < min) {System.out.println("钱太少,不去");
return null;}System.out.println("A抽取" + money * 0.6 + "提成");
return method.invoke(Xulaoshi, money * 0.4);
}
return method.invoke(Xulaoshi, args);}};
// static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
drawer p = (drawer) Proxy.newProxyInstance(loader, interfaces, h);
p.sing(100);
p.draw(1000000);
p.sleep();
}
}

以上是关于java动态代理(知识点扫盲)的主要内容,如果未能解决你的问题,请参考以下文章

学习Spring必学的Java基础知识----动态代理

nginx 扫盲

Spring 动态代理基础知识

《Java基础知识》动态代理(InvocationHandler)详解

Java动态代理浅度分析

java 知识点 扫盲