自己new的对象怎么注入spring管理的对象

本文介绍两种在Spring框架中实现Bean自动装配的方法。一种是通过AutowireCapableBeanFactory对象直接创建并注入依赖,另一种是通过自定义基类在构造时利用反射完成依赖注入。文章详细解释了每种方法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方式一(推荐):

思路:

获取AutowireCapableBeanFactory对象,然后调用注入bean对象方法.

代码:

主要调用ApplicationContextUtils.newAutoWiredInstance()方法生成已经注入springbean的实例.

工具类:

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    //方式一:传Class对象
    //新建对象实例并注入其他springbean
    public static <T> T newAutoWiredInstance(Class<T> beanClass){
        return (T)applicationContext.getAutowireCapableBeanFactory()
                .autowire(beanClass, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
    }

    //方式二:传bean对象
    //已经new出来的对象进行注入
    public static <T> T autowire(T bean){
        applicationContext.getAutowireCapableBeanFactory()
                        .autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtils.applicationContext = applicationContext;
    }


}

自己的类(不受spring管理的bean):

public class AutoWiredBean {

    @Autowired
    private ServiceA serviceA;


    @Autowired
    private ServiceB serviceB;


    public void test(){
        serviceB.sayHello();
    }


}

测试:

        //自己new对象
        AutoWiredBean autoWiredBean1 = new AutoWiredBean();
        ApplicationContextUtils.autowire(autoWiredBean1);
        autoWiredBean1.test();

        //只是传Class对象
        AutoWiredBean autoWiredBean = ApplicationContextUtils.newAutoWiredInstance(AutoWiredBean.class);
        autoWiredBean.test();

方式二(不推荐):

思路:

1. 自己搞个类,注入ApplicationContext,然后构造方法里面对类的属性进行反射注入.

2. 然后需要自己new的类都来集成这个类

理解:initNewService因为是被spring容器管理的,且实现了ApplicationContextAware(或者ServletContextAware),所以在spring容器初始化的时候回注入ApplicationContextAware,我们把它保存在类中,并设置为static,因此每个继承此类的对象都能拿到ApplicationContextAware。然后继承类初始化的时候,我们通过属性的类型到容器中找到对应的对象,并通过反射注入进来。

代码:

@Service
public class InitNewService implements ApplicationContextAware {

    private static Logger logger = LoggerFactory.getLogger(InitNewService.class);

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 将继承此类的service中的字段(注解了@Autowired 或者@Resource)等注入进来
     */
    public InitNewService(){

        if (this.applicationContext == null){
            return;
        }

        if (this.getClass().isAnnotationPresent(org.springframework.stereotype.Service.class)
                || this.getClass().isAnnotationPresent(org.springframework.stereotype.Controller.class)
                || this.getClass().isAnnotationPresent(org.springframework.stereotype.Component.class) ){
            return;
        }

        Class clazz = this.getClass();
        do {
            Field[] fields = clazz.getDeclaredFields();
            for (Field f : fields) {
                if (f.isAnnotationPresent(org.springframework.beans.factory.annotation.Autowired.class)
                        || f.isAnnotationPresent(javax.annotation.Resource.class)){

                    try {
                        String simpleName = f.getType().getSimpleName();
                        String beanName = StrUtils.toLowerCaseFirstOne(simpleName);

                        Object bean = applicationContext.getBean(beanName);
                        if (bean == null){
                            return;
                        }

                        boolean accessible = f.isAccessible();
                        f.setAccessible(true);
                        f.set(this,bean);
                        f.setAccessible(accessible);
                    }catch (Exception e){
                        logger.error(clazz.getName() + "当new对象注入类" + f.getName() + "的时候,发生了错误",e);
                        e.printStackTrace();
                    }

                }
            }
            clazz = clazz.getSuperclass();
        } while (clazz != Object.class);
    }


}

<think>首先,用户的问题是基于之前的引用,但引用是关于Spring框架的,具体是Spring容器管理对象与直接使用new创建对象的区别。用户说:"我想理解Spring容器管理对象与直接使用new创建对象的区别 请问spring 容器管理对象new 创建对象的区别"。所以,我需要专注于回答这个问题。 我的回答必须遵守系统级指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 参考的引用内容: - 引用[1]:解释为什么用Spring容器而不是直接new。 - 引用[2]:比较Spring容器和new的优势。 - 引用[3]:区别Spring注入对象new对象。 - 引用[4]:Spring容器创建对象的特点。 - 引用[5]:XML配置示例。 我需要基于这些引用构建回答。引用是站内的,所以我应该在回答中自然地引用它们。 回答结构: 1. **介绍**:简要解释Spring容器和new操作。 2. **主要区别**:逐步列出关键区别点。 3. **优势分析**:为什么Spring容器更好。 4. **示例**:提供一个简单的代码示例。 5. **相关问题**:生成相关问题。 关键区别点(基于引用): - **控制反转(IoC)**:Spring容器负责对象的创建和管理,而不是开发者直接new。 - **依赖注入(DI)**:Spring自动注入依赖,而new需要手动管理。 - **生命周期管理**:Spring管理对象的整个生命周期,包括初始化、销毁等。 - **解耦和灵活性**:使用Spring使代码更解耦,易于测试和维护。 - **性能考虑**:Spring容器在启动时创建所有bean,而new是随需创建。 - **异常处理**:如引用[3]提到,new对象中使用自动注入可能报空指针异常。 生成相关问题: - 基于用户问题,生成2-3个相关问题。 - 例如:如何配置Spring bean?Spring容器如何实现依赖注入?等。 使用中文回答。 现在,结构化回答: 1. **引言**:解释Spring容器和new的基本概念。 2. **核心区别**: - 创建方式:Spring容器通过配置文件或注解创建对象new是直接实例化。 - 依赖管理Spring自动注入依赖;new需要手动设置。 - 作用域:Spring支持单例、原型等作用域;new每次创建新实例。 - 测试和维护:Spring便于模拟和替换依赖;new耦合度高。 3. **优势总结**:为什么Spring更好(基于引用)。 4. **代码示例**:展示一个简单的Spring bean配置和new的对比。 5. **相关问题**:列出2-3个相关问题。 确保引用:在相关部分末尾添加引用标识,如[^1]。 最终输出格式: - 回答内容。 - 相关问题。</think>### Spring容器管理对象与直接使用new创建对象的区别 在Java开发中,对象的创建和管理是核心任务。Spring框架通过容器(如`ApplicationContext`)管理对象,而传统方式则使用`new`关键字直接实例化对象。这两种方式在控制权、依赖管理、灵活性和维护性上有显著差异。下面我将逐步分析这些区别,帮助您深入理解。回答基于Spring框架的设计原则和相关引用内容,确保真实可靠。 #### 1. **控制权反转(Inversion of Control, IoC)** - **Spring容器**:对象Spring容器负责创建和管理,开发者只需定义对象(bean)的配置(如XML或注解),容器在启动时自动实例化所有bean并存储在一个Map中[^4]。这实现了控制权从开发者转移到容器,称为IoC。 - 例如,Spring容器默认调用类的无参构造方法创建对象,并在应用启动时一次性创建所有bean[^4]。 - **直接使用new**:开发者完全控制对象的创建时机和方式,每次调用`new`都会直接实例化一个新对象。这增加了代码耦合度,因为对象创建逻辑硬编码在业务代码中。 - **关键区别**:Spring的IoC减少了代码侵入性,而new方式要求开发者手动管理所有实例化过程。这使Spring更适用于大型应用,避免“硬编码”问题[^1][^2]。 #### 2. **依赖注入(Dependency Injection, DI)** - **Spring容器**:通过DI机制自动注入对象间的依赖关系。例如,在XML配置中,使用`<property>`或`@Autowired`注解,Spring会自动将依赖对象注入到目标bean中[^5]。这解耦了组件,使代码更模块化。 - 如引用[5]所示:`<property name="userDao" ref="userDaoImpl"/>`,Spring自动将`userDaoImpl`注入到service中,无需手动设置。 - **直接使用new**:开发者必须手动创建和设置依赖对象。例如,在service类中,需要显式调用`new UserDaoImpl()`来实例化依赖。这容易导致代码冗余和错误,如未正确处理依赖可能引发空指针异常[^3]。 - **关键区别**:Spring的DI提升了代码的可测试性和可维护性,因为依赖可以轻松替换(如使用Mock对象测试);new方式则需修改源代码来调整依赖,增加了维护成本[^2][^3]。 #### 3. **对象生命周期和作用域管理** - **Spring容器**:支持多种作用域(如单例singleton、原型prototype)。默认是单例模式,容器只创建一个bean实例供所有请求共享;原型模式则每次请求都创建新实例[^4]。容器还管理对象的初始化(如`@PostConstruct`)和销毁回调,简化资源管理。 - 引用[4]提到:Spring容器在启动时创建所有对象并存储,这优化了性能,但可能增加启动时间。 - **直接使用new**:对象的生命周期完全由开发者控制。每次`new`都生成一个新实例,作用域限于创建它的上下文(如方法内部)。这缺乏统一的生命周期管理,容易导致内存泄漏或资源未释放问题。 - **关键区别**:Spring提供标准化的生命周期管理,适合复杂应用;new方式更轻量但适用于简单场景,如小型工具类[^1][^4]。 #### 4. **解耦和灵活性** - **Spring容器**:通过配置或注解定义对象,业务代码不依赖具体实现类。这实现了松耦合,便于更换实现(如从MySQL切换到Oracle数据库,只需修改配置而不改代码)[^5]。 - **直接使用new**:代码直接绑定到具体类,变更实现需要修改多处源代码。例如,如果`UserDao`接口有多个实现,new方式需在代码中硬编码具体类名,降低灵活性。 - **关键区别**:Spring的解耦设计提高了代码的可扩展性和可维护性,而new方式在应用规模扩大时易导致“代码腐化”[^2][^3]。 #### 5. **性能与异常处理** - **Spring容器**:启动时创建所有bean,可能增加初始开销,但运行时访问速度快。容器还处理依赖注入的异常,如自动注入失败时抛出`BeanCreationException`,避免空指针问题[^3][^4]。 - **直接使用new**:对象按需创建,启动快,但运行时可能频繁实例化影响性能。手动管理依赖时,易忽略null检查,导致空指针异常(如引用[3]所述:在new对象中使用自动注入会报空指针)[^3]。 - **关键区别**:Spring优化了长期运行的性能,但需权衡启动时间;new方式更轻便但易出错,尤其在高并发场景[^4]。 #### 代码示例对比 以下是一个简单示例,展示Spring容器与new方式的区别: - **Spring配置(XML方式)**: ```xml <beans> <bean id="userDao" class="com.example.UserDaoImpl"/> <bean id="userService" class="com.example.UserService"> <property name="userDao" ref="userDao"/> <!-- Spring自动注入依赖 --> </bean> </beans> ``` 在代码中,只需通过容器获取对象: ```java ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService service = context.getBean("userService"); // 容器管理对象 ``` - **直接使用new**: ```java public class UserService { private UserDao userDao; public UserService() { this.userDao = new UserDaoImpl(); // 手动创建依赖 } } // 使用时 UserService service = new UserService(); // 开发者控制实例化 ``` 此方式需在构造函数中硬编码依赖,变更实现时需修改源代码。 #### 总结 Spring容器管理对象通过IoC和DI机制,提供了控制权反转、自动依赖注入、统一生命周期管理和解耦优势,特别适合中大型企业应用[^1][^2]。而直接使用`new`创建对象简单直接,但耦合度高、维护困难,适用于小型或工具类场景。选择哪种方式取决于应用复杂度:Spring提升了可扩展性和可靠性,而new方式在快速原型开发中更高效[^3][^5]。 如果您有具体代码场景,我可以进一步分析优化建议!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值