IOC(控制反转)、DI(依赖注入)

IOC(控制反转)是一种设计思想,旨在实现类之间的高内聚和低耦合。DI(依赖注入)是IOC的核心,通过容器动态地为对象提供所需依赖。Spring框架利用反射实现依赖注入。本文介绍了如何通过不同方式实现DI,如注解如@Component、@Repository、@Service、@Controller等,并探讨了@Autowired、@Qualifier等注解在对象属性赋值中的作用,以及对象范围和生命周期相关的注解,如@Scope、@Lazy、@PostConstruct和@PreDestroy。此外,还提及了@Configuration、@ComponentScan等在纯注解开发中的应用。

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

ioc存在的意义:“高内聚,低耦合”
ioc可以使类与类之间-高内聚: 类内部的关系越紧密越好;低耦合: 类与类的关联越少越好。用自己的话说就是类与类之间需要调用的时候,我们再也不是直接去调用了,而是通过ioc容器,运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
采用了依赖注入,在初始化的过程中就不可避免的会写大量的new。这里IoC容器就解决了这个问题。这个容器可以自动对你的代码进行初始化,你只需要维护一个Configuration(可以是xml可以是一段代码),而不用每次初始化一辆车都要亲手去写那一大段初始化的代码。这是引入IoC Container的第一个好处

给ioc的定义:
创建对象
 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
给对象属性赋值
DI(Dependency Injection,依赖注入),Ioc的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection依赖注入)来实现的。

主要通过:下面三个方法实现在这里插入图片描述
FileSystemXmlApplicationContext与ClassPathXMLApplicationContext的实现:
在这里插入图片描述
annotationXmlApplicationContext的实现方法:
创建对象的四个注解:

@Component 创建对象加入容器。如:工具类,除了dao、service、controller其他以外的类使用此注解。

@Repository 同@Component ,用于修饰持久层的类。

@Service 同@Component ,用于修饰业务层的类。

@Controller 同@Component ,用于修饰表现层的类。

依赖注入的四个注解:

@Autowired 给对象属性赋值: 1. 根据类型注入(字段类型,方法形参类型); 2. 根据名称注入(字段名称,方法形参名称)

@Qualifier 要配置@Autowired使用,可以只根据名称注入。 也可以在纯注解中单独使用。

@Resource 了解,jdk1.8以后不提供此注解的支持。

@Value 直接给简单类型属性赋值,或获取配置文件值。

对象范围、生命周期相关的注解:

@Scope 指定对象为singleton单例,或prototype多例。

@Lazy 延迟初始化(使用较少,因为我们大多数单例的对象都是在启动时候创建。)

@PostConstruct 修饰方法,修饰的方法会在创建对象之后执行。

@PreDestroy 修饰方法,修饰的方法会在调用容器的close()方法时候执行。

纯注解开发用到的一些注解:

@Configuration 指定注解配置类

@ComponentScan 指定注解扫描的包

@Import 导入其他注解配置类

@PropertySource 加载类路径下的配置文件

@Value、@Qualifier

@Bean 修饰方法,会自动把方法返回值加入ioc容器

### IOC控制反转)和DI依赖注入) #### 什么是IoC IoC控制反转,是一种设计模式,其核心在于将原本由程序代码直接操控的对象创建过程交给了专门的容器来处理。这样做的主要目的是为了减少组件之间的耦合度,使得应用程序更加模块化、易于管理和扩展[^1]。 在传统的编程模型中,调用者负责初始化它所需要的资源和服务;而在采用IoC的设计里,则是由外部环境——通常是框架或库,在适当的时候提供这些必要的协作对象给调用方使用[^2]。 #### 什么是DI DI代表依赖注入,这是实现IoC的一种具体方法论。通过这种方式可以更清晰地表达出各个软件单元之间存在的相互依存关系,并且简化了新功能加入时所需修改的工作量。简单来说,就是让某个类不需要自己去寻找它的依赖项而是被动接收它们[^3]。 对于开发者而言,这意味着可以在不改动原有逻辑的前提下轻松替换掉某些特定部分的功能实现,从而提高了系统的灵活性以及便于进行单元测试等活动[^4]。 #### 实现方式 ##### XML配置文件 早期版本中的Spring应用广泛采用了基于XML的方式来进行Bean定义: ```xml <beans> <!-- 定义UserServiceImpl bean --> <bean id="userService" class="com.example.service.UserServiceImpl"> <!-- 设置属性值 --> <property name="userRepository" ref="userRepository"/> </bean> <!-- 定义UserRepositoryImpl bean --> <bean id="userRepository" class="com.example.repository.UserRepositoryImpl"/> </beans> ``` 上述例子展示了如何利用`<bean>`标签声明服务层与数据访问层间的关联关系,其中`ref`关键字用于指示目标引用另一个已注册过的Bean实例。 ##### Java Config 随着Java语言的发展,越来越多的人倾向于使用纯编码的方式来完成同样的事情: ```java @Configuration public class AppConfig { @Bean public UserService userService() { return new UserServiceImpl(userRepository()); } @Bean public UserRepository userRepository(){ return new UserRepositoryImpl(); } } ``` 这段代码片段同样表达了相同的内容,但是是以更为直观的形式呈现出来的。这里借助于`@Configuration`注解标记该类为配置源之一,而内部的方法则分别对应着不同类型的工厂方法,用来生产相应的单例对象供整个上下文共享使用。 ##### 注解驱动 最后一种也是目前最流行的做法便是依靠各种各样的元数据标注来自动生成所需的映射表结构: ```java @Service public class UserServiceImpl implements UserService{ private final UserRepository userRepository; @Autowired public UserServiceImpl(UserRepository userRepository){ this.userRepository = userRepository; } } @Repository public class UserRepositoryImpl implements UserRepository{} ``` 在这个场景下,只要确保所有参与组装操作的角色都已经被正确地标记上了合适的标签即可,剩下的工作交给Spring Boot自动完成就好。特别是当涉及到大量第三方库集成的情况下,这种方法的优势尤为明显。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值