文章目录
- 一、单元测试:JUnit框架精要
- 1.1 单元测试核心概念
- 1.2 JUnit快速入门实战
- 基础步骤:
- 断言机制验证结果
- 1.3 JUnit核心注解解析
- 二、反射机制:框架设计的基石
- 2.1 反射核心概念
- 2.2 获取Class对象的三种方式
- 2.3 反射操作类成分
- 获取并执行构造器
- 操作成员变量
- 调用成员方法
- 2.4 反射高级应用
- 突破泛型限制
- 开发通用对象框架
- 三、注解:元编程利器
- 3.1 注解基础概念
- 3.2 元注解:注解的注解
- 3.3 注解解析实战
- 3.4 反射应用场景:模拟JUnit测试框架
- 四、动态代理:优雅的增强方案
- 4.1 代理模式核心思想
- 4.2 JDK动态代理实现
- 定义接口与实现类
- 创建代理工具类
- 使用代理对象
- 4.3 动态代理应用:性能监控
- 五、总结:四大技术的关联与应用
本文全面解析Java高级技术核心内容:单元测试、反射机制、注解应用与动态代理实现,通过理论讲解与代码实践助你掌握框架底层原理
一、单元测试:JUnit框架精要
1.1 单元测试核心概念
单元测试是针对**最小功能单元(方法级别)**编写的测试代码,用于验证功能正确性。传统main方法测试存在三大痛点:
- 无法灵活选择测试方法
- 不能自动生成测试报告
- 测试过程无法自动化
JUnit作为第三方开源测试框架,完美解决了这些问题:
- ✅ 支持选择性执行测试方法或批量执行
- ✅ 自动生成可视化测试报告(绿色成功/红色失败)
- ✅ 高度灵活的测试代码编写
1.2 JUnit快速入门实战
基础步骤:
- 创建测试类
- 编写公共无参无返回值的测试方法
- 使用@Test注解标记测试方法(idea 可以直接导入,Alt+Enter)
- 在测试方法中调用被测代码(在@Test的方法任务地方右击,点击run 方法名)
// StringUtil工具类
public class StringUtil {public static void printNumber(String name) {System.out.println("名字长度:" + name.length());}
}// 测试类
public class StringUtilTest {@Testpublic void testPrintNumber() {StringUtil.printNumber("admin");StringUtil.printNumber(null); // 测试异常情况}
}
断言机制验证结果
@Test
public void testGetMaxIndex() {int index = StringUtil.getMaxIndex("admin");// 断言预测结果:期望值4, 实际值indexAssert.assertEquals("方法内部有Bug", 4, index);
}
注意:很多个测试类中多个测试方法,可以直接点击项目,右击run ‘All Tests’
1.3 JUnit核心注解解析
注解 | JUnit4 | JUnit5 | 执行时机 |
---|---|---|---|
初始化 | @Before | @BeforeEach | 每个@Test方法前执行 |
清理 | @After | @AfterEach | 每个@Test方法后执行 |
全局初始化 | @BeforeClass | @BeforeAll | 所有测试方法前执行(static) |
全局清理 | @AfterClass | @AfterAll | 所有测试方法后执行(static) |
资源管理实战:
public class ResourceTest {private static Socket socket;@BeforeClasspublic static void init() {socket = new Socket(); // 初始化资源}@AfterClasspublic static void cleanup() {socket.close(); // 释放资源}@Testpublic void testNetwork() {// 使用socket进行测试}
}
二、反射机制:框架设计的基石
2.1 反射核心概念
反射是在运行时获取类的字节码对象(Class对象),并动态解析类的全部成分:
- 🏗️ 构造器(Constructor对象)
- 📦 成员变量(Field对象)
- ⚙️ 成员方法(Method对象)
应用场景:
- IDE代码提示功能
- Spring框架的IoC容器
- MyBatis的ORM映射
- 通用工具类开发
2.2 获取Class对象的三种方式
// 1. 类名.class
Class c1 = Student.class;// 2. Class.forName("全类名")
Class c2 = Class.forName("com.example.Student");// 3. 对象.getClass()
Student s = new Student();
Class c3 = s.getClass();System.out.println(c1 == c2); // true
System.out.println(c2 == c3); // true
2.3 反射操作类成分
获取并执行构造器
Class<Cat> catClass = Cat.class;// 获取私有构造器
Constructor<Cat> constructor = catClass.getDeclaredConstructor(String.class, int.class);// 暴力反射(解除私有限制)
constructor.setAccessible(true); // 执行构造器创建实例
Cat cat = constructor.newInstance("Tom", 3);
操作成员变量
Field nameField = catClass.getDeclaredField("name");
nameField.setAccessible(true);// 设置字段值
nameField.set(cat, "Jerry");// 获取字段值
String name = (String) nameField.get(cat);
调用成员方法
Method runMethod = catClass.getDeclaredMethod("run");
runMethod.setAccessible(true);// 调用无参方法
runMethod.invoke(cat);// 调用有参方法
Method eatMethod = catClass.getDeclaredMethod("eat", String.class);
eatMethod.setAccessible(true);
String result = (String) eatMethod.invoke(cat, "fish");
2.4 反射高级应用
突破泛型限制
// 编译时泛型检查
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
// list.add("字符串"); // 编译报错// 运行时通过反射绕过泛型检查
Method addMethod = ArrayList.class.getDeclaredMethod("add", Object.class);
addMethod.invoke(list, "字符串"); // 成功添加
开发通用对象框架
public class ObjectFrame {public static void saveObject(Object obj) throws Exception {Class<?> c = obj.getClass();Field[] fields = c.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);//禁止检查访问控制String fieldName = field.getName();Object value = field.get(obj);// 写入字段名和值到文件}}
}// 使用示例
Student stu = new Student("张三", 20);
ObjectFrame.saveObject(stu);
三、注解:元编程利器
3.1 注解基础概念
注解(Annotation)是JDK5引入的代码标记机制,用于对类、方法、字段等进行标注。核心作用:
- 🔖 标记程序元素
- 💡 提供元数据信息
- ⚙️ 驱动特殊处理逻辑
自定义注解格式:
public @interface MyAnnotation {// 属性声明String value(); int count() default 1;String[] tags();
}
3.2 元注解:注解的注解
元注解用于修饰自定义注解:
元注解 | 作用 | 常用值 |
---|---|---|
@Target | 指定注解使用范围 | TYPE, FIELD, METHOD等 |
@Retention | 指定注解生命周期 | SOURCE, CLASS, RUNTIME |
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {String value(); // 书名double price() default 100;String[] authors(); // 作者数组
}
3.3 注解解析实战
@Book(value = "Java核心技术", authors = {"Cay S. Horstmann"})
public class Textbook {@Book(value = "Effective Java", price = 128.0, authors = {"Joshua Bloch"})public void recommend() {}
}// 解析类注解
Class<Textbook> clazz = Textbook.class;
if (clazz.isAnnotationPresent(Book.class)) {Book book = clazz.getAnnotation(Book.class);System.out.println("书名: " + book.value());
}// 解析方法注解
Method method = clazz.getMethod("recommend");
if (method.isAnnotationPresent(Book.class)) {Book book = method.getAnnotation(Book.class);System.out.println("价格: " + book.price());
}
3.4 反射应用场景:模拟JUnit测试框架
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest {}public class TestRunner {public static void main(String[] args) throws Exception {Class<?> testClass = MyTestClass.class;Object instance = testClass.newInstance();for (Method method : testClass.getDeclaredMethods()) {if (method.isAnnotationPresent(MyTest.class)) {method.invoke(instance); // 执行测试方法}}}
}
四、动态代理:优雅的增强方案
4.1 代理模式核心思想
当目标对象无法或不想直接完成操作时,通过代理对象控制对目标对象的访问:
- 💼 代理对象持有目标对象引用
- 🔄 代理对象拦截方法调用
- ➕ 在方法执行前后添加额外操作
4.2 JDK动态代理实现
定义接口与实现类
public interface Star {String sing(String song);void dance();
}public class BigStar implements Star {private String name;public BigStar(String name) {this.name = name;}@Overridepublic String sing(String song) {return name + "演唱:" + song;}@Overridepublic void dance() {System.out.println(name + "跳舞");}
}
创建代理工具类
public class ProxyUtil {public static Star createProxy(BigStar target) {return (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),new Class[]{Star.class},(proxy, method, args) -> {// 前置增强if ("sing".equals(method.getName())) {System.out.println("准备话筒,收费20万");} else if ("dance".equals(method.getName())) {System.out.println("准备场地,收费100万");}// 调用目标方法Object result = method.invoke(target, args);// 后置增强System.out.println("表演结束,结算费用");return result;});}
}
使用代理对象
public static void main(String[] args) {BigStar star = new BigStar("杨超越");Star proxy = ProxyUtil.createProxy(star);String result = proxy.sing("卡路里");System.out.println(result);proxy.dance();
}
4.3 动态代理应用:性能监控
public class PerformanceProxy {public static UserService createProxy(UserService target) {return (UserService) Proxy.newProxyInstance(PerformanceProxy.class.getClassLoader(),new Class[]{UserService.class},(proxy, method, args) -> {long start = System.currentTimeMillis();Object result = method.invoke(target, args);long end = System.currentTimeMillis();System.out.println(method.getName() + "方法执行耗时: " + (end - start) + "ms");return result;});}
}// 使用示例
UserService userService = new UserServiceImpl();
UserService proxy = PerformanceProxy.createProxy(userService);
proxy.login("admin", "123456");
五、总结:四大技术的关联与应用
技术 | 核心能力 | 典型应用场景 |
---|---|---|
单元测试 | 自动化验证代码逻辑 | 保障代码质量,回归测试 |
反射 | 运行时动态解析类结构 | 框架设计,动态代码生成 |
注解 | 声明式配置程序元素 | 简化配置,驱动框架行为 |
动态代理 | 无侵入增强对象功能 | AOP实现,性能监控,事务管理 |
技术联动示例:
- 使用注解标记测试方法(@Test)
- 通过反射解析测试类信息
- 利用动态代理增强测试方法(添加事务控制)
- 通过单元测试验证功能正确性
掌握这四大Java高级技术,不仅能编写更健壮高效的代码,更能深入理解主流框架的设计思想,为成为架构师奠定坚实基础。
学习建议:
- 先掌握单元测试保证代码质量
- 深入理解反射机制原理
- 练习自定义注解及解析
- 动手实现动态代理案例
- 研究Spring等框架的源码实现