HacKerQWQ的博客空间

Java代理学习

Word count: 1.4kReading time: 5 min
2021/08/09 Share

代理模式概念

  • 代理就是帮别人做事情,如:工厂的中介,中介负责为工厂招收工人,那么中介就是工厂的代理;客户通过商家购买东西,商家向厂家购买货物,商家就是工厂的代理

  • 在开发中存在a类需要调用c类的方法,完成某一个功能,但是c禁止a调用。这时,可以在a和c之间创建一个b类代理,a类访问b类,b类访问c类。例如:登录的时候需要进行短信验证,这个时候代理就是中国移动的子公司来完成短信的发送功能

  • 代理模式就是为其他对象提供一种代理来控制这个对象的访问,在某些情况下一个对象不适合或不能直接引用另一个对象,而代理对象可以在客户类和目标对象直接起到中介的作用

    img

  • 功能增强:其中目标对象实现真正的功能,但是代理对象可以对目标对象的功能做进一步的扩充,例如打官司的时候,原告陈述事实,律师则在这基础上进行修饰以及法律条文的引用

    image-20210809234026941

代理的规则:被代理类和代理类都必须实现同一个接口的方法

静态代理

张三(被代理的对象)犯法了,但是在法庭上不能为自己辩护,这时候律师(代理类的对象)就起到了代理的作用,当法官问(调用)张三(被代理的对象)的时候,需要通过律师来陈述。

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
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test{
public static void main(String[] args) {
//静态代理
specker specker = new Lawyer();
specker.speck();
}
}

//定义接口
interface specker{
public void speck();
}

//ZhangSan类(被代理类)实现接口
class ZhangSan implements specker{
@Override
public void speck() {
System.out.println("我要赚钱!");
}
}

//Lawyer类(代理类)实现接口并增强
class Lawyer implements specker{
@Override
public void speck() {
ZhangSan zhangsan = new ZhangSan();
System.out.println("根据刑法,你赚钱方法有问题!");
//功能增强
zhangsan.speck();
System.out.println("你要坐牢!");
}
}
  • 定义了specker接口和speck()方法,ZhangSan类和Lawyer类都继承并实现
  • Lawyer调用方法时在ZhangSan的基础上进行补充增强

调用截图:

image-20210810000908139

动态代理

动态代理是利用的反射机制动态地生成代理的对象,我们不需要知道谁代理谁。代理类的那部分代码被固定下来了,不会因为业务的增加而逐渐庞大。

JDK代理

JDK动态代理规则:

  1. 实现代理的类必须实现InvocationHandler接口
  2. 在代理类的invoke编写调用的方法
  3. 通过Proxy.newProxyInstance(classloader,interface、invocationhandler)创建代理类并实现实际类型的转换
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
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test{
public static void main(String[] args) {

//创建ZhangSan的代理类
LawyerProxy lawyerProxy = new LawyerProxy(new ZhangSan());
//通过Proxy.newInstance()创建代理类,并且传入classloader、interface的class、代理类的实例对象
specker specker = (specker) Proxy.newProxyInstance(Test.class.getClassLoader(),new Class[]{specker.class},lawyerProxy);
specker.speck();

//创建Lisi的代理类
LawyerProxy lawyerProxy1 = new LawyerProxy(new Lisi());
specker specker1 = (specker) Proxy.newProxyInstance(Test.class.getClassLoader(),new Class[]{specker.class},lawyerProxy);
specker1.speck();
}
}

//接口
interface specker{
public void speck();
}
//Lisi类实现specker接口
class Lisi implements specker{
@Override
//Lisi的speck方法
public void speck() {
System.out.println("别问我,我什么都不知道!");
}
}
//ZhangSan类实现specker接口
class ZhangSan implements specker{
@Override
//ZhangSan的speck()方法
public void speck() {
System.out.println("我要赚钱!");
}
}
//动态代理类LawyerProxy实现InvocationHandler接口
class LawyerProxy implements InvocationHandler{

Object object;
//通过构造函数将实际调用的对象赋值给object属性
public LawyerProxy(Object object){
this.object=object;
}
//通过重写invoke方法,接收proxy、method、args三个参数实现动态代理
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("speck")){
System.out.println("根据刑法,你赚钱方法有问题!");
//反射调用this.object中的method方法,并传入args参数
method.invoke(this.object,args);
System.out.println("你要坐牢!");
}
return null;
}
}

通过CGLIB实现动态代理

有些类有同样的方法名,但是没有实现接口,一般是引入的jar包,这时就可以使用CGLIB的动态代理

原理是继承,通过继承目标类创建它的子类,在子类中重写父类中的方法,实现功能的修改

1392562-20200415104132082-639153375

  • 需要导入jar包:cglib.jar,核心包和依赖包(spring_core.jar已经集成了这两个包,因此,导入此包即可)
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
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

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

public class Test{
public static void main(String[] args) {
//创建代理类的实例对象
LawyerIntercepter lawyerIntercepter = new LawyerIntercepter(new Lisi());
//通过Enhancer.create(要代理类的class,代理类的实例对象)
Lisi lisi = (Lisi) Enhancer.create(Lisi.class,lawyerIntercepter);
//通过cglib动态代理调用speck方法
lisi.speck();
}
}

//外部的Lisi类,被代理类
class Lisi{
public void speck() {
System.out.println("别问我,我什么都不知道!");
}
}

//代理类LawyerIntercepter实现MethodInterceptor接口
class LawyerIntercepter implements MethodInterceptor{
private Object object;
LawyerIntercepter(Object object){
this.object=object;
}
//重写intercept方法,objects相当于args
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if (method.getName().equals("speck")){
System.out.println("这是java的cglib动态代理");
method.invoke(object,objects);
System.out.println("你有罪!");
}
return null;
}
}
CATALOG
  1. 1. 代理模式概念
  2. 2. 静态代理
  3. 3. 动态代理
    1. 3.1. JDK代理
    2. 3.2. 通过CGLIB实现动态代理