505. Java 反射 - BeanFactory 讲解

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);
        }
    }
}

流程拆解:

  1. 收集参数类型:把传入的 "Hello" → String.class,确保找到正确的构造方法。
  2. 查找构造器:beanClass.getConstructor(argumentsClasses) 找到合适的构造方法。
  3. 实例化对象:调用 newInstance(arguments) 创建并返回实例。

5.总结

  • 枚举单例模式:相比懒汉式/饿汉式,枚举单例更简洁、安全。
  • 参数类型匹配问题:如果构造器参数是 int,但你传的是 Integer,可能找不到。可以用 getDeclaredConstructors()+类型兼容检查来增强。
  • 现实意义:
    • 在 Spring 中,BeanFactory 就是所有 IOC 容器的核心接口。
    • 我们这里的实现很简化,但展示了反射如何动态创建对象。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容