1.1 注解和反射
以前 学习过 注解和 反射。但是 真的 没有 理解 它 能干嘛。
其实 注解和反射 更多的是 应用于 设计一个框架上。而且 反射 用到的最多!不要 一提到 反射 就想到 注解,一些 实战的 框架,在实现某些 功能的时候,都是直接用的 反射,并未与 注解连用。
那么为什么 要 与 注解联用呢,最主要的原因 在于 我们在使用框架的时候 更加方便。
- 设计一个框架 设计技术点
反射机制、自定义注解、设计模式(23种)、AOP 技术(判断 目标是否应用了 自定义注解,然后再通过 反射获取,进行二次处理。)、netty技术(客户端和服务端 通讯)、spring 的架构设计原理(主要是为了 整合在 spring 中)、springboot 自定义插件、多线程 或 JUC 等等
- 反射技术
使用反射机制 可以动态获取到 class 的信息,比如 方法的信息、方法的参数、属性 等等。
反射技术应用的场景
-
JDBC 加载驱动连接 class.forname()
-
Spring 容器框架 IOC 实例化对象
-
自定义注解 生效(反射 + AOP)
当初学习的时候 为啥 说 没太了解 注解和反射 的联用呢,是因为 我们 只知道 注解是那样定义的,然后 能通过 反射拿到信息,但是这个 注解写了之后 有啥真实意义吗?好像又 没有。。。 -
第三方 核心的 框架 都会用到 反射技术的。
反射技术的 使用
- 反射技术 来 新建 对象
Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
aClss.newInstance();//它 会默认 走 无参构造,去 new 一个 对象。
如何知道 目标 应用了注解
在我们 获取了 目标后,是 可以通过 目标 来获取 注解的。如果能拿到 注解,就证明 该目标 应用了注解,那我们就可以 来进行 一些 操作了。
1.2 识别 注解 并用反射 实战
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
public class 实战 {
Class<?> C = null;
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IOException {
Class<?> c = Class.forName("Student");
实战 aop = new 实战(c);
}
public 实战(Class<?> C) throws IOException {
this.C = C;
Field[] fields = C.getDeclaredFields();
System.out.println(fields);
for(Field f:fields){
f.setAccessible(true);// 开权限
FileOutputStream file = new FileOutputStream("data.txt", true);
Fieldmu Fmu = f.getAnnotation(Fieldmu.class);
System.out.println(Fmu);
if(Fmu != null){// 也就是 我们 有注解,那么我们 可以做 很多的操作
String columnNameMu = Fmu.columnName();
String typeMu = Fmu.type();
int length = Fmu.length();
String lemngthMu = String.valueOf(length);
String ret = "["+f.getName() + "字段]\n" +"columnNameMu="+columnNameMu+"\n"+"type="+typeMu+"\n"
+ "lemngth="+lemngthMu+"\n";
file.write(ret.getBytes(StandardCharsets.UTF_8));
System.out.println(f.getName() + ":处理完成!");
}
}
}
}
简单的 打破 双亲委派,可以 动态的 加载类,然后 创建 Obj 对象。
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
public class 实战 {
Class<?> C = null;
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IOException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
MyClassLoader myClassLoader = new MyClassLoader("C:\\Users\\muqua\\Desktop\\NotesANDLearn\\" +
"JAVA复习\\注解和反射\\注解和反射\\out\\production\\注解和反射");
Class<?> c = myClassLoader.findClass("Student");
Method print = c.getDeclaredMethod("print");
Object student = c.newInstance();
System.out.println(student.getClass().getSimpleName());
print.invoke(student);
//实战 aop = new 实战(c);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true){
String msg = reader.readLine();
if(msg.equals("重加载")){
myClassLoader = new MyClassLoader("C:\\Users\\muqua\\Desktop\\NotesANDLearn\\" +
"JAVA复习\\注解和反射\\注解和反射\\out\\production\\注解和反射");
c = myClassLoader.findClass("Student");
print = c.getDeclaredMethod("print");
student = c.newInstance();
print.invoke(student);
//s.print();
}
}
}
public 实战(Class<?> C) throws IOException {
this.C = C;
Field[] fields = C.getDeclaredFields();
System.out.println(fields);
for(Field f:fields){
f.setAccessible(true);// 开权限
FileOutputStream file = new FileOutputStream("data.txt", true);
Fieldmu Fmu = f.getAnnotation(Fieldmu.class);
System.out.println(Fmu);
if(Fmu != null){// 也就是 我们 有注解,那么我们 可以做 很多的操作
String columnNameMu = Fmu.columnName();
String typeMu = Fmu.type();
int length = Fmu.length();
String lemngthMu = String.valueOf(length);
String ret = "["+f.getName() + "字段]\n" +"columnNameMu="+columnNameMu+"\n"+"type="+typeMu+"\n"
+ "lemngth="+lemngthMu+"\n";
file.write(ret.getBytes(StandardCharsets.UTF_8));
System.out.println(f.getName() + ":处理完成!");
}
}
}
}
自定义 类加载器
import sun.misc.PerfCounter;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.ProtectionDomain;
/**
* Created by IntelliJ IDEA
* User: yqm02
* Date: 2021/8/22
* Time: 17:25
*/
public class MyClassLoader extends ClassLoader {
/**
* 加载器加载的路径
* */
private String classPath;
public MyClassLoader(String path) {
this.classPath = path;
}
protected byte[] loadByte(String name) throws IOException {
name = name.replaceAll("\\.", "/");
String path = classPath + "/" + name + ".class";
FileInputStream fileInputStream = new FileInputStream(path);
int len = fileInputStream.available();
byte[] data = new byte[len];
fileInputStream.read(data);
fileInputStream.close();
return data;
}
@Override
protected Class<?> findClass(String name) {
byte[] data = null;
try {
data = loadByte(name);
} catch (IOException e) {
e.printStackTrace();
}
return defineClass(name, data, 0, data.length);
}
}
但现在 还有一个问题,就是 我不知道为什么 通过 类加载器 获取的 Class 对象 使用 newInstance() 方法 创建的 实例化对象 无法进行 强转 变为 Student