0%

动态代理

动态代理

  • 为什么需要代理 ?

无侵入式的给对象增加额外的功能。

调用者 $\rightarrow$ 代理 $\rightarrow$ 对象

(对象功能太多的话,可以通过代理转移部分职责。)

  • 代理长什么样 ?

代理里面就是对象想要被代理的方法

(对象有什么方法想被代理,代理就一定要有对应的方法。)

  • Java通过什么保证代理的样子 ?

通过接口保证,后面的对象和代理需要实现同一个接口,接口中就是被代理的所有方法。

动态代理实例

Interface : Star

1
2
3
4
5
6
7
8
9
package com.qust;

public interface Star {
// 唱歌
public abstract String sing(String name);

// 跳舞
public abstract void dance();
}

Class : BigStar

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
package com.qust;

public class BigStar implements Star{
private String name;

// 唱歌
@Override
public String sing(String name) {
System.out.println(this.name + "正在唱" + name);
return "谢谢";
}

// 跳舞
@Override
public void dance() {
System.out.println(this.name + "正在跳舞");
}

public BigStar() {
}

public BigStar(String name) {
this.name = name;
}

/**
* 获取
* @return name
*/
public String getName() {
return name;
}

/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}

public String toString() {
return "BigStar{name = " + name + "}";
}
}

Class : Proxyutil

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
package com.qust;

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

/**
* 类的作用 :
* 创建一个代理
*/


public class ProxyUtil {

/**
* 方法的作用 : 创建一个代理
* @param bigStar
* 返回值 :
* 给 BigStar 创建的代理
*/
public static Star createProxy(BigStar bigStar) {
/**
* java.lang.reflect.Proxy类 :提供了为对象产生代理对象的方法
* public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* 参数一 : 用于指定哪个类加载器
* 参数二 : 指定接口,这些接口用于指定生成的代理长什么样,也就是有哪些方法
* 参数三 :指定生成的代理对象要干什么事情
*/
Star star = (Star) Proxy.newProxyInstance(
BigStar.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("sing".equals(method.getName())) {
System.out.println("准备话筒,收钱");
}
else if("dance".equals(method.getName())) {
System.out.println("准备场地,收钱");
}

return method.invoke(bigStar, args);

}
}
);

return star;
}

}

Class : Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.qust;

//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void main(String[] args) {

// 获取代理对象
BigStar bigStar = new BigStar("鸡哥");
Star proxy = ProxyUtil.createProxy(bigStar);

// 调用对应方法
String result = proxy.sing("只因你太美");
System.out.println(result);

proxy.dance();
}
}

Usage

usage就是这个东西在哪里被使用了

Javabean

JavaBean 是一种符合特定规范的 Java 类,用于封装数据并通过 getter/setter 方法访问。

Ptg 可以一键生成 Javabean

class<?> []

class<?>[] 是 Java 中的一种数组类型,表示一个元素类型为 任意类型的 Class 对象数组

1
2
3
4
5
6
7
8
9
10
11
public class Example {
public static void main(String[] args) {
// 创建一个 Class<?> 数组
Class<?>[] classes = {String.class, Integer.class, Double.class};

// 输出每个元素的类名
for (Class<?> clazz : classes) {
System.out.println(clazz.getName());
}
}
}
1
2
3
java.lang.String
java.lang.Integer
java.lang.Double

打包成 jar 包会去除所有注释吗?

不会,打包成 JAR 包时注释不会被自动去除

具体原因是:

  1. 注释属于源码的一部分,它们不会被编译到 .class 文件中,因此在编译阶段就被丢弃了。JAR 包中存储的是编译后的字节码(.class 文件),而不是源码(.java 文件)。

  2. 如果 JAR 包中需要包含源码(比如 -sources JAR),源码中的注释会被保留,但这些注释只是存储在 .java 文件中,供开发者阅读使用,不影响运行时。

    总结

  • 普通 JAR 包(包含 .class 文件):没有注释,因为注释早在编译时被去掉了。

  • 源码 JAR 包(包含 .java 文件):注释会被保留。
    如果你的目标是生成一个干净的 JAR 包,避免泄露源码或敏感注释,可以通过排除 .java 文件的方式只打包字节码。

term

  • invoke v. 调用

  • utility /juːˈtɪləti/ n. 实用工具

  • AOP,Aspect-Oriented Programming,面向切面编程

  • proxy /ˈprɒksi/ n. 代理权,代理人