You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bean类内部实例化其他类的可行性、机制、优劣及优化方案探讨

Hey there! Let's tackle your questions step by step—they're all centered around Spring Bean management, which is a common pain point when you're getting comfortable with dependency injection. Let's break it down:

1. Can a Bean class instantiate another class internally? If yes, how to avoid this?

Absolutely, you can manually instantiate another class inside a Spring Bean (like using new MyOtherClass() directly). But this defeats most of the benefits of using Spring's dependency injection (DI) container. The manually created object won't be managed by Spring—no lifecycle hooks, no dependency injection for it, no adherence to Spring's scoping rules (like singleton), etc.

To avoid this practice (and follow Spring best practices), here's what you should do:

  • Inject the dependency instead: Register the target class (MyOtherClass in your example) as a Spring Bean using annotations like @Component, @Service, or @Repository, or by defining an explicit @Bean method in a configuration class. Then use constructor injection (preferred) or @Autowired to get that managed Bean into your original class.
  • Use Spring-managed factories if dynamic creation is needed: If you need to create instances on the fly, use a Spring-managed factory Bean instead of manual new calls. This keeps Spring in control of object lifecycle.
  • Avoid hardcoded new calls for managed objects: Any class that needs dependencies, lifecycle management, or to be swapped out (like for testing) should be handled by Spring's container.
2. Deep dive into manual instantiation inside a registered Bean

Let's unpack the scenario you described: Your main class is registered as a Spring Bean, but it internally instantiates another class (MyOtherClass) manually. Here's the breakdown:

How does this mechanism work?

When Spring creates your registered Bean (e.g., MyBean), it calls its constructor (or uses a factory method). Inside that constructor, your manual new MyOtherClass() creates an instance completely outside Spring's oversight:

  • Spring has no idea this MyOtherClass instance exists, so it won't inject any dependencies that MyOtherClass might require.
  • Spring won't apply lifecycle callbacks like @PostConstruct or @PreDestroy to this instance.
  • If MyBean is prototype-scoped, every new MyBean instance will get a brand new MyOtherClass instance; if MyBean is singleton, you'll have one MyOtherClass instance tied to that singleton. But none of this follows Spring's built-in scoping rules.

Is it safe to instantiate new objects during Bean injection?

Technically, it's "safe" in that it won't crash your application—but it's a bad practice with significant downsides. The risks include:

  • Unmanaged dependencies: If MyOtherClass needs its own dependencies (like a database repository), you'll have to instantiate those manually too, leading to tight coupling and messy, hard-to-maintain code.
  • Poor testability: You can't easily mock MyOtherClass in unit tests for MyBean, since the instance is hardcoded with new.
  • No lifecycle control: You can't leverage Spring's features to initialize or clean up MyOtherClass instances.
  • Scoping mismatches: If MyOtherClass should be a singleton but MyBean is prototype, you'll end up with multiple MyOtherClass instances which might not align with your intended behavior.

Pros and cons of this manual instantiation approach

Pros

  • Quick and trivial for simple classes with no dependencies or lifecycle requirements.
  • No need to register the secondary class as a Bean (though this is a short-term convenience that leads to long-term technical debt).

Cons

  • Tight coupling: MyBean is directly tied to MyOtherClass's implementation, making it impossible to swap MyOtherClass for another implementation (like a mock) without modifying MyBean's code.
  • Unmanaged objects: As mentioned, no Spring DI, lifecycle management, or scoping for the manually created instance.
  • Maintainability issues: As your application grows, manually managing object creation becomes error-prone and difficult to debug.

Is registering MyOtherClass as a Bean and using @Autowired feasible? (And is @Autowired + getMyclass() redundant?)

Absolutely—this is the standard, recommended way to handle dependencies in Spring. Let's assume your revised code looks something like this:

// MyOtherClass now registered as a Bean
@Component
public class MyOtherClass {
    // ... class logic ...
}

// MyBean with constructor injection (preferred approach)
@Component
public class MyBean {
    private final MyOtherClass myOtherClass;

    public MyBean(MyOtherClass myOtherClass) {
        this.myOtherClass = myOtherClass;
    }

    // Getter method
    public MyOtherClass getMyclass() {
        return myOtherClass;
    }
}

Or if you're using field injection (less preferred, but still valid):

@Component
public class MyBean {
    @Autowired
    private MyOtherClass myOtherClass;

    public MyOtherClass getMyclass() {
        return myOtherClass;
    }
}

Now, about redundancy:

  • @Autowired (or constructor injection) is how you tell Spring to inject the managed MyOtherClass Bean into MyBean. It's essential for letting Spring handle the dependency.
  • The getMyclass() method is only necessary if other classes need to access myOtherClass through MyBean. If MyBean doesn't need to expose this dependency to the outside, the getter is redundant and can be removed.
  • A quick best practice: Constructor injection is always better than field injection. It makes dependencies explicit, allows the field to be final (for immutability), and makes unit testing easier (you can pass a mock MyOtherClass directly in the constructor without needing Spring's container).

内容的提问来源于stack exchange,提问作者user6219476

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:21:05