Java 反射、依赖注入与 AOP 全面解析

一、依赖注入(DI)概述

依赖注入是现代 Java 框架(如 Spring)的核心思想。它通过将对象所依赖的组件从外部注入,解耦代码依赖,提高代码的可测试性和扩展性。

1. 构造器注入(Constructor Injection)

构造器注入是通过类的有参构造函数传入依赖,确保依赖在对象创建时就已经赋值。

@Service 
public class UserService { 
private final UserRepository userRepository; 
// 构造器注入,依赖注入时由 Spring 自动调用此构造函数 
public UserService(UserRepository userRepository) { 
this.userRepository = userRepository; } 

public void createUser() { userRepository.save(); } }

优点:

  • 依赖为 final,不可变,线程安全。

  • 必须提供依赖,避免空指针。

  • 方便单元测试,明确依赖。


2. 注解注入(@Autowired)

通过注解标注字段、构造器或 setter,Spring 会自动注入依赖。

字段注入示例(不推荐):



@Service public class UserService {
 @Autowired private UserRepository userRepository; 
public void createUser() { 
userRepository.save(); } }

setter 注入示例:



@Service public class UserService { 
private UserRepository userRepository; 
@Autowired 
public void setUserRepository(UserRepository userRepository) {
 this.userRepository = userRepository; } }

**注意:**字段注入可能导致构造过程中依赖为 null,容易出现空指针异常。


3. 为什么推荐构造器注入?

  • Spring 容器在调用构造器时,依赖已经准备好,避免构造函数里使用未注入依赖导致空指针。

  • 依赖明确,代码更加安全和易维护。

  • 单元测试方便,只需传入 mock 对象。


二、Java 反射基础及示例

反射是 Java 提供的一种运行时动态访问和操作类的机制

1. 反射能做什么?

  • 动态获取类的结构(字段、方法、构造器)

  • 动态创建对象实例

  • 动态调用方法

  • 访问私有成员(破坏封装)


2. 反射示例代码

假设有如下 User 类:



public class User { 
private String name = "默认"; 
public User() {} public User(String name) { 
this.name = name; } 
public void sayHello() { 
System.out.println("Hello, I am " + name); } 
public void setName(String name) { this.name = name; } }

用反射创建对象并调用方法:



public class ReflectDemo { 
public static void main(String[] args) throws Exception { 
// 1. 获取类对象 
Class<?> clazz = Class.forName("User"); 
// 2. 创建无参构造对象 
Object user = clazz.getDeclaredConstructor().newInstance(); 
// 3. 调用 setName 方法 
Method setName = clazz.getMethod("setName", String.class); 
setName.invoke(user, "Alice"); 
// 4. 调用 sayHello 方法 
Method sayHello = clazz.getMethod("sayHello"); 
sayHello.invoke(user); } }

输出:

css

复制编辑

Hello, I am Alice


3. 为什么有时候不用直接 new

因为:

  • 代码编写时不一定知道要使用哪个类

  • 框架需要根据类名字符串动态加载类实例

  • 实现插件、配置驱动的动态扩展

反射使代码更加灵活、可扩展。


三、Spring AOP 与动态增强

1. 什么是 AOP?

AOP(面向切面编程)允许我们将日志、事务、权限等横切关注点抽离出来,动态地织入业务逻辑中,而不用修改业务代码。


2. 动态增强的概念

动态增强指的是在运行时,通过代理和反射技术,在方法执行前后或异常时插入额外代码。


3. Spring AOP 实现原理简述

  • Spring 使用 JDK 动态代理或 CGLIB 动态代理创建目标类代理。

  • 代理类的方法调用会被拦截,执行增强逻辑(通知)。

  • 最终通过反射调用原始目标方法。


4. AOP 代码示例

定义切面:

@Aspect 
@Component 
public class LogAspect { 
@Before("execution(* com.example.service.*.*(..))") 
public void beforeAdvice() { System.out.println("方法执行前打印日志"); } @AfterReturning("execution(* com.example.service.*.*(..))") 
public void afterAdvice() { 
System.out.println("方法执行后记录操作"); 
} }

调用业务方法时:

orderService.createOrder();

实际调用流程:

scss

代理对象的 createOrder() -> 执行 beforeAdvice() -> 通过反射调用真实 createOrder() -> 执行 afterAdvice()


5. 反射在 AOP 中的作用

反射用于:

  • 获取方法信息,动态判断调用哪个方法

  • 调用目标方法(Method.invoke()

  • 动态实现通知(前置、后置、异常)


四、总结

主题关键点
依赖注入构造器注入推荐,字段注入易空指针
反射运行时动态访问类信息,动态创建对象和调用方法
为什么不用 new编译时绑定,反射支持运行时灵活动态加载
AOP 与动态增强利用代理和反射动态织入横切逻辑
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值