505. Java 反射 - BeanFactory 讲解
1. 什么是 BeanFactory?
在企业级开发中,我们经常需要创建并管理对象(Bean)。
而不是到处写 new,我们可以通过一个 Bean 工厂 来统一负责对象的创建。
👉 简单理解:
- 你告诉工厂:“我要一个
Message对象,并且构造参数是"Hello"”。 - 工厂帮你找到合适的构造方法,创建并返回这个对象。
这和我们前面讲到的 依赖注入 (DI) 有点类似,不过这里更偏向于一个通用的对象工厂。
2. 示例类:Message
我们先定义一个 record 类型(JDK 16+ 引入,简洁不可变数据类):
public record Message(String message) {
public Message {
Objects.requireNonNull(message);
}
}
public final class Message {
private final String message;
public Message(String message) {
this.message = Objects.requireNonNull(message);
}
public String message() {
return message;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Message other = (Message) obj;
return Objects.equals(message, other.message);
}
@Override
public int hashCode() {
return Objects.hash(message);
}
@Override
public String toString() {
return "Message[message=" + message + "]";
}
}
特点:
-
record会自动生成构造方法、toString()、equals()等。 - 构造参数不能为空(使用
Objects.requireNonNull做校验)。
3. 使用 BeanFactory 的场景
void main() {
BeanFactory beanFactory = BeanFactory.INSTANCE;
Message message1 = beanFactory.getInstanceOf(Message.class, "Hello");
System.out.println("Message 1 = " + message1);
Message message2 = beanFactory.getInstanceOf(Message.class, "world");
System.out.println("Message 2 = " + message2);
}
输出结果:
Message 1 = Message[message=Hello]
Message 2 = Message[message=world]
这里没有 new Message("Hello"),而是交给工厂来完成。
4. BeanFactory 的实现
我们用 枚举单例模式 实现 BeanFactory(枚举天生线程安全,推荐用来写单例):
public enum BeanFactory {
INSTANCE;
public <T> T getInstanceOf(Class<T> beanClass, Object... arguments) {
try {
// 1️⃣ 获取参数类型数组
Class<?>[] argumentsClasses =
Arrays.stream(arguments)
.map(Object::getClass)
.toArray(Class<?>[]::new);
// 2️⃣ 找到匹配的构造器
Constructor<T> beanConstructor = beanClass.getConstructor(argumentsClasses);
// 3️⃣ 调用构造器创建对象
return beanConstructor.newInstance(arguments);
} catch (NoSuchMethodException |
InvocationTargetException |
InstantiationException |
IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
流程拆解:
-
收集参数类型:把传入的
"Hello"→String.class,确保找到正确的构造方法。 -
查找构造器:
beanClass.getConstructor(argumentsClasses)找到合适的构造方法。 -
实例化对象:调用
newInstance(arguments)创建并返回实例。
5.总结
- 枚举单例模式:相比懒汉式/饿汉式,枚举单例更简洁、安全。
-
参数类型匹配问题:如果构造器参数是
int,但你传的是Integer,可能找不到。可以用getDeclaredConstructors()+类型兼容检查来增强。 -
现实意义:
- 在 Spring 中,
BeanFactory就是所有 IOC 容器的核心接口。 - 我们这里的实现很简化,但展示了反射如何动态创建对象。
- 在 Spring 中,