墨风如雪博客

  • 源码小店
  • 导航站
  • 登录
  • java
  • 资源分享
让AI使用变得如此简单
  1. 首页
  2. java
  3. spring
  4. 正文

Spring DI:依赖注入的完整指南

2023年 5月 31日 122点热度 0人点赞 0条评论

一、什么是DI(Dependency Injection)依赖注入?

1.1 传统编程模式的不足

在传统的Java编程中,对象之间通常是通过创建和管理对象的实例来解决依赖关系。这种方式存在以下不足:

  • 代码复杂度高
  • 对象之间的依赖关系紧密耦合,难以维护和测试
  • 对象的单元测试和集成测试难以实现

1.2 DI的概念和作用

DI(Dependency Injection)依赖注入是一种通过外部注入对象的依赖关系来解决对象之间依赖关系的方法。DI的作用如下:

  • 降低代码复杂度
  • 降低对象之间的耦合性
  • 方便对象的单元测试和集成测试

1.3 DI和IOC(Inversion of Control)的关系

DI和IOC(Inversion of Control)是两个密不可分的概念。IOC是一种设计模式,通过将对象的创建和管理交由容器负责,实现了对象之间的解耦和复用。而DI是IOC的一种具体实现方式,通过将依赖关系外置,实现了对象之间的解耦和复用。因此,可以说DI是IOC的一种实现方式。

二、Spring DI的实现原理

Spring DI的实现原理主要有以下几种方式。

2.1 构造函数注入

构造函数注入是一种常见的DI方式,它通过对象的构造函数来注入依赖关系。示例如下:

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    // methods
}

在上面的示例中,UserServiceImpl类的构造函数接收一个UserDao实例,并将其赋值给类的成员变量userDao。

2.2 Setter方法注入

Setter方法注入是另一种常见的DI方式,它通过对象的Setter方法来注入依赖关系。示例如下:

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
       this.userDao = userDao;
    }

    // methods
}

在上面的示例中,UserServiceImpl类的setUserDao方法接收一个UserDao实例,并将其赋值给类的成员变量userDao。

2.3 接口注入

接口注入是一种比较灵活的DI方式,它通过接口的实现类来注入依赖关系。示例如下:

public interface UserService {
    void addUser(User user);
}

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void addUser(User user) {
        userDao.addUser(user);
    }
}

在上面的示例中,UserServiceImpl实现了UserService接口,通过构造函数注入了UserDao实例,并在addUser方法中使用了UserDao实例。

2.4 自动装配

自动装配是一种比较方便的DI方式,它通过容器自动查找并注入依赖关系。Spring DI提供了多种自动装配方式,包括按名称、按类型、按注解等方式。示例如下:

@Service
public class UserServiceImpl implements UserService {
   @Autowired
    private UserDao userDao;

    // methods
}

在上面的示例中,使用@Autowired注解自动装配了UserDao实例。

三、Spring DI的注解

3.1 @Autowired注解

@Autowired注解是Spring DI中最常用的注解之一,用于自动装配Bean的依赖关系。它可以用于字段、方法、构造方法和参数上。示例如下:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser(User user) {
        userDao.addUser(user);
    }
}

在上面的示例中,使用@Autowired注解自动装配了UserDao实例,同时还使用@Autowired注解标注了构造方法和方法参数。

3.2 @Qualifier注解

@Qualifier注解用于指定自动装配Bean的名称或ID,用于解决多个Bean实例的冲突问题。示例如下:

@Service
public class UserServiceImpl implements UserService {
   @Autowired
    @Qualifier("userDaoImpl")
    private UserDaouserDao;

    // methods
}

在上面的示例中,使用@Qualifier注解指定了userDao实例的名称为"userDaoImpl",用于解决多个UserDao实例的冲突问题。

3.3 @Resource注解

@Resource注解是一种用于注入依赖关系的注解,它可以通过名称或类型来指定依赖关系。示例如下:

@Service
public class UserServiceImpl implements UserService {
   @Resource(name = "userDaoImpl")
    private UserDao userDao;

    // methods
}

在上面的示例中,使用@Resource注解指定了userDao实例的名称为"userDaoImpl",用于注入依赖关系。

3.4 @Value注解

@Value注解用于注入配置文件中的属性值或表达式。示例如下:

@Service
public class UserServiceImpl implements UserService {
    @Value("${maxPageSize}")
    private int maxPageSize;

    // methods
}

在上面的示例中,使用@Value注解注入了配置文件中的属性值maxPageSize。

四、Spring DI的配置方式

4.1 基于XML的配置方式

基于XML的配置方式是Spring DI最传统的配置方式。它通过在XML文件中定义Bean和Bean之间的依赖关系来实现DI。示例如下:

<beans>
    <bean id="userDaoImpl" class="com.example.dao.UserDaoImpl"></bean>
    <bean id="userService" class="com.example.service.UserServiceImpl">
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
</beans>

在上面的示例中,定义了两个Bean:userDaoImpl和userService,并在userService的property属性中手动注入了userDaoImpl。

4.2 基于注解的配置方式

基于注解的配置方式是Spring DI中比较常用的配置方式,它通过在类或方法上添加注解来实现DI。示例如下:

@Configuration
public class AppConfig {
    @Bean
    public UserDao userDaoImpl() {
        return new UserDaoImpl();
    }

    @Bean
    public UserService userService() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(userDaoImpl());
        return userService;
    }
}

在上面的示例中,定义了一个Java配置类AppConfig,其中定义了两个Bean:userDaoImpl和userService,并在userService的方法中手动注入了userDaoImpl。

4.3 基于Java配置的方式

基于Java配置的方式是一种比较灵活的配置方式,它通过Java代码来实现DI。示例如下:

@Configuration
public class AppConfig {
    @Bean
    public UserDao userDaoImpl() {
        return new UserDaoImpl();
    }

    @Bean
    public UserService userService() {
        return new UserServiceImpl(userDaoImpl());
    }
}

在上面的示例中,使用@Configuration注解标注了Java配置类AppConfig,定义了两个Bean:userDaoImpl和userService,并在userService的方法中通过构造函数注入了userDaoImpl。

五、Spring DI的作用域

Spring DI提供了多种作用域,用于控制Bean实例的生命周期。常用的作用域有单例、多例、原型、会话和请求等。示例如下:

@Service
@Scope("prototype")
public class UserServiceImpl implements UserService {
    // methods
}

在上面的示例中,使用@Scope注解定义了Bean的作用域为多例,即每次请求获取的都是一个新的实例。

六、Spring DI的扩展点

Spring DI提供了多种扩展点,用于增强DI的功能和灵活性。常用的扩展点有使用FactoryBean创建Bean、自定义BeanPostProcessor和BeanFactoryPostProcessor、使用@Import注解导入其他配置类和使用@Profile注解指定不同环境下的Bean等。示例如下:

6.1 使用FactoryBean创建Bean

public class MyFactoryBean implements FactoryBean<UserDao> {
   @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

在上面的示例中,定义了一个实现了FactoryBean接口的MyFactoryBean类,用于创建UserDao实例。

6.2 自定义BeanPostProcessor和BeanFactoryPostProcessor

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof UserServiceImpl) {
            UserServiceImpl userService = (UserServiceImpl) bean;
            userDao = new UserDaoImpl();
            userService.setUserDao(userDao);
        }
        return bean;
    }
}

在上面的示例中,定义了一个实现了BeanPostProcessor接口的MyBeanPostProcessor类,用于在Bean初始化前后做一些操作,例如在UserServiceImpl实例化后手动注入UserDao实例。

6.3 使用@Import注解导入其他配置类

@Configuration
public class DaoConfig {
    @Bean
    public UserDao userDao() {
        return new UserDaoImpl();
    }
}

@Configuration
@Import(DaoConfig.class)
public class ServiceConfig {
    @Autowired
    private UserDao userDao;

    @Bean
    public UserService userService() {
        return new UserServiceImpl(userDao);
    }
}

在上面的示例中,使用@Import注解将DaoConfig配置类导入到ServiceConfig配置类中,以便在ServiceConfig中使用userDao实例。

6.4 使用@Profile注解指定不同环境下的Bean

@Configuration
public class DevConfig {
    @Bean
    @Profile("dev")
    public UserDao userDao() {
        return new UserDaoImpl();
    }
}

@Configuration
public class ProdConfig {
    @Bean
    @Profile("prod")
    public UserDao userDao() {
        return new UserDaoImpl();
    }
}

在上面的示例中,使用@Profile注解分别指定了DevConfig和ProdConfig配置类中的userDao实例在不同的环境下使用。在开发环境中,使用DevConfig配置类中定义的userDao实例,在生产环境中,使用ProdConfig配置类中定义的userDao实例。

七、总结

本文介绍了Java Spring DI的基本概念、实现原理、注解、配置方式、作用域和扩展点等内容。通过学习本文,读者可以了解到DI的作用和优势,掌握Spring DI的实现原理和常用注解、配置方式和作用域,以及了解Spring DI的扩展点和灵活性。DI是Java编程中不可或缺的一部分,掌握好DI的知识可以帮助开发者编写出更加简洁、灵活和易于维护的代码。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: AOP DI ioc java spring spring特性 依赖注入 循环依赖
最后更新:2023年 5月 23日

墨风如雪

一个热爱生活,热爱分享的程序员

打赏 点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

墨风如雪

一个热爱生活,热爱分享的程序员

最新 热点 随机
最新 热点 随机
Sora触手可及!微软必应AI视频生成器,全民创作时代来临? 阿里WebAgent开源:引领自主搜索新纪元 重磅炸弹!字节跳动开源BAGEL:70亿参数,统一多模态理解与生成,AI“全能王”诞生记! 小米MiMo-VL:7B参数,怎么就成了多模态界的“越级打怪王”? 炸裂!DeepSeek 8B 量化版降临:告别显存焦虑,你的 3080 Ti 也能玩转顶级大模型了! 美团炸场AI圈:点外卖点出个软件?用「对话式编程」重塑生产力!
炸裂!微软这门免费AI Agent新手课,GitHub近2万星,简直是宝藏!ComfyUI“打通任督二脉”:直接调用Veo2、GPT-4o等65大模型!一键串联你的AI工作流AI圈炸锅了!Mistral Medium 3:性能 SOTA,成本打骨折,企业玩家的新宠?字节终于开源“扣子”同款引擎了!FlowGram:AI 时代的可视化工作流利器告别“微信黑箱”!Chatlog:让你的聊天记录也能拥有“AI大脑”!字节跳动 Seed-Coder-8B:不靠人工洗数据,这80亿参数的小模型如何写出顶尖代码?
每日一道算法题:判断对称二叉树 Java 当中的只要组成部分 JVM 国产AI视频迈入“高可控”时代?Vidu Q1重磅发布,这几个点太炸裂了! 算法详解:八皇后问题 告别工具切换噩梦!阿里巴巴通义万相 Wan2.1-VACE:一个模型,通吃视频生成与编辑! java 微服务框架技术Apache ServiceComb
标签聚合
算法 设计模式 deepseek spring 教程 AI 动态规划 java

COPYRIGHT © 2023 墨风如雪博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

免责声明 - 隐私政策