java基础之动态代理笔记

前言

java的代理机制,包括静态代理和动态代理

静态代理和动态代理中都有使用到接口

关于接口,个人认为需要意识到以下几点:

1.一个类继承了类A和执行了接口B,A与B在同一层级

2.接口的使用体现代码的多态性

3.接口体现的是代码的规范性,在现实生活中就是”如果你要….,就必须要……“

正文

静态代理机制

例子:小明做饭需要买鱼和买鸡蛋,但是小明没有空,于是小明托小红,小兰去帮忙买鱼和鸡蛋。

在这个例子里小明作为被代理类,小红,小兰作为代理类,将帮小明分别去买这两样东西,因为代理类和被代理类的目的买这些东西,所以这里实现两个接口。

1
2
3
4
5
6
7
interface Buyfish{
void payForFish();
}

interface Buyegg{
void payForegg();
}

然后想要买鱼和鸡蛋的但是腿脚不便的人需要做的事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//被代理类
class BuyFishPeople implements Buyfish{

@Override
public void payForFish() {
System.out.println("为买鱼付了60元");
}
}


//被代理类
class BuyeggPeople implements Buyegg{

@Override
public void payForegg() {
System.out.println("为买鸡蛋付了60元");
}
}

帮忙买鱼和鸡蛋的人需要做的事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//代理类
class ProxyBuyFish implements Buyfish{
private Buyfish obj;//体现多态
public ProxyBuyFish(Buyfish obj){
System.out.println("去海鲜市场");
this.obj = obj;
}

@Override
public void payForFish() {
obj.payForFish();
}
}

//代理类
class ProxyBuyegg implements Buyegg{

private Buyegg obj;
public ProxyBuyegg(Buyegg obj){
this.obj=obj;
}
@Override
public void payForegg(){
System.out.println("去买鸡蛋的超市");
obj.payForegg();
}
}

主程序中

1
2
3
4
5
6
7
8
9
10
public void test(){
BuyFishPeople xiaoming = new BuyFishPeople();
ProxyBuyFish xiaohong = new ProxyBuyFish(xiaoming);
xiaohong.payForFish();

BuyeggPeople xiaoming2 = new BuyeggPeople();
ProxyBuyegg xiaolan = new ProxyBuyegg(xiaoming2);
xiaolan.payForegg();

}

image-20201214000200503

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.c0okb.ProxyTest;

/*
静态代理
*/

import org.junit.Test;

//接口
interface Buyfish{

void payForFish();
}

//被代理类
class BuyFishPeople implements Buyfish{

@Override
public void payForFish() {

System.out.println("买鱼付了60元");
}
}

//代理类
class ProxyBuyFish implements Buyfish{
private Buyfish obj;
public ProxyBuyFish(Buyfish obj){
System.out.println("去海鲜市场");
this.obj = obj;
}

@Override
public void payForFish() {
obj.payForFish();
}
}

interface Buyegg{

void payForegg();
}

//被代理类
class BuyeggPeople implements Buyegg{

@Override
public void payForegg() {

System.out.println("为买鸡蛋付了60");
}
}

//代理类
class ProxyBuyegg implements Buyegg{

private Buyegg obj;
public ProxyBuyegg(Buyegg obj){
this.obj=obj;
}
@Override
public void payForegg(){
System.out.println("去买鸡蛋的超市");
obj.payForegg();
}
}

public class DynamicProxyTest2 {

@Test
public void test(){
BuyFishPeople xiaoming = new BuyFishPeople();
ProxyBuyFish xiaohong = new ProxyBuyFish(xiaoming);
xiaohong.payForFish();

BuyeggPeople xiaoming2 = new BuyeggPeople();
ProxyBuyegg xiaolan = new ProxyBuyegg(xiaoming2);
xiaolan.payForegg();
}

}

但是静态代理有一个很严重的问题,每一个代理只能完成一种需求,假如小明还想买鸡鸭鹅狗猫,那他还需要叫更多人。在代码中就显得这很繁琐。

于是提出动态代理机制

动态代理机制

动态代理中有两个问题需要解决

1
2
3
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。

问题二:当通过代理类的对象调用方法时,如何动态地去调用被代理类中的同名方法。

小明的需求不变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//接口
interface Buyfish{

void payForFish();
}

//被代理类
class BuyFishPeople implements Buyfish{

@Override
public void payForFish() {
System.out.println("买鱼付了60元");
}
}

interface Buyegg{

void payForegg();
}

//被代理类
class BuyeggPeople implements Buyegg{

@Override
public void payForegg() {

System.out.println("为买鸡蛋付了60");
}
}

这时候帮忙买东西的人需要完成的事

1
2
3
4
5
6
7
8
9
//代理类
class ProxyFactory1{
//调用此方法,返回一个代理类的对象,解决问题一
public static Object getProxy(Object obj){//被代理类
BuyMyInvocationHandler handler = new BuyMyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}

在代理类中实现方法getProxy(Object obj),这个方法中的参数obj就是我们需要被代理的类。这个方法将会返回一个被代理类的对象。

其中关键的函数

1
Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);

其中

1
2
obj.getClass().getClassLoader() 获得被代理类的类加载器
obj.getClass().getInterfaces() 获得被代理类实现的接口

最后一个参数handler

1
2
BuyMyInvocationHandler handler = new BuyMyInvocationHandler();
handler.bind(obj);

这是我们自己创建的类,用于调用被调用类的指定方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class BuyMyInvocationHandler implements InvocationHandler{
private Object obj;//需要使用被代理类的对象进行赋值
public void bind(Object obj){
this.obj = obj;
}
//当我们通过代理类的对象,调用方法a时,就会自动调用如下方法:invoke()
//将被代理类要执行的方法a的功能声明在invoke方法中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
//obj:被代理类的对象
Object ReturnValue = method.invoke(obj,args);
//上述方法的返回值作为当前类的中的invoke()的返回值
return ReturnValue;
}
}

这个类实现接口InvocationHandler,该接口中的方法如下,在实现该接口情况下,我们重写这个方法

image-20201214002345738

1
2
3
4
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ReturnValue = method.invoke(obj,args);
return ReturnValue;
}

动态代理中有两个问题需要解决

1
2
3
4
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
通过创建方法 public static Object getProxy(Object obj) 实现动态创建代理类
问题二:当通过代理类的对象调用方法时,如何动态地去调用被代理类中的同名方法。
通过 class BuyMyInvocationHandler implements InvocationHandler 这个类来实现动态,调用被代理类的同名方法

主程序

1
2
3
4
5
6
7
8
    public void test(){
BuyFishPeople xiaoming = new BuyFishPeople();
BuyeggPeople xiaoming2 = new BuyeggPeople();
Buyfish xiaohong = (Buyfish) ProxyFactory1.getProxy(xiaoming);
Buyegg xiaohong2 = (Buyegg) ProxyFactory1.getProxy(xiaoming2);
xiaohong.payForFish();
xiaohong2.payForegg();
}

当我们执行

1
xiaohong.payForFish();

将会调用

1
2
3
4
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ReturnValue = method.invoke(obj,args);
return ReturnValue;
}

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.c0okb.ProxyTest;

import org.junit.Test;

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

//接口
interface Buyfish{

void payForFish();
}

//被代理类
class BuyFishPeople implements Buyfish{

@Override
public void payForFish() {
System.out.println("买鱼付了60元");
}
}

//接口
interface Buyegg{

void payForegg();
}

//被代理类
class BuyeggPeople implements Buyegg{

@Override
public void payForegg() {

System.out.println("为买鸡蛋付了60");
}
}



//代理类
class ProxyFactory1{


public static Object getProxy(Object obj){
BuyMyInvocationHandler handler = new BuyMyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}

}

class BuyMyInvocationHandler implements InvocationHandler{
private Object obj;
public void bind(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ReturnValue = method.invoke(obj,args);
return ReturnValue;
}
}

public class DynamicProxyTest2 {

public void test(){
BuyFishPeople xiaoming = new BuyFishPeople();
BuyeggPeople xiaoming2 = new BuyeggPeople();
Buyfish xiaohong = (Buyfish) ProxyFactory1.getProxy(xiaoming);
Buyegg xiaohong2 = (Buyegg) ProxyFactory1.getProxy(xiaoming2);
xiaohong.payForFish();
xiaohong2.payForegg();
}
}
Author: 我是小吴啦
Link: http://yoursite.com/2020/12/10/java%E5%9F%BA%E7%A1%80%E4%B9%8B%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E7%AC%94%E8%AE%B0/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.