前记:spring源码编译已经在前篇写过,现在开始去学习spring的源码()
前因:对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础。现在,伴随着工业级应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系(1、依赖对象多次创建 2、依赖关系复杂),因此,架构师和设计师对于系统的分析和设计,将面临更大的挑战。对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。
耦合关系不仅会出现在对象与对象之间,也会出现在软件系统的各模块之间,以及软件系统和硬件系统之间。如何降低系统之间、模块之间和对象之间的耦合度过高的问题,软件专家Michael Mattson提出了IOC理论,用来实现对象之间的“解耦”,目前这个理论已经被成功地应用到实践当中,很多的J2EE项目均采用了IOC框架产品Spring。
一、IoC容器设计理念
IoC也称为依赖注⼊(dependency injection, DI)。它是⼀个对象定义依赖关系的过程,也就是 说,对象只通过构造函数参数、⼯⼚⽅法的参数或对象实例构造或从⼯⼚⽅法返回后在对象实例上设置的属性来定义它们所使⽤的其他对象。然后容器在创建bean时注⼊这些依赖项。这 个过程基本上是bean的逆过程,因此称为控制反转(IoC)
在Spring中,构成应⽤程序主⼲并由Spring IoC容器管理的对象称为bean。bean是由Spring IoC容器实例化、组装和管理的对象。
IoC容器设计理念:通过容器统⼀对象的构建⽅式,并且⾃动维护对象的依赖关系。
1、控制反转:
对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
2、 IOC的别名:依赖注入(DI)
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
二、Spring实现IOC的使用与分析
1、bean的装配⽅式
1)、xml配置方式
注:由于配置方式过于繁琐,不推荐使用了。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mxy" class="com.mxy.spring.bean.Mxy"/>
</beans>
2)、实现FactoryBean
思考:FactoryBean和BeanFactory的区别?
AbstractBeanFactory#getObjectForBeanInstance
!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)
下期会深入研究
3)、@Component ,@ComponentScan
@Component, @Repository,@Service, @Controller
@Component是通⽤注解,其他三个注解是这个注解的拓展,并且具有了特定的功能
@Repository注解在持久层中,具有将数据库操作抛出的原⽣异常翻译转化为spring的持
久层异常的功能。
@Service层是业务逻辑层注解,这个注解只是标注该类处于业务逻辑层。
@Controller层是spring-mvc的注解,具有将请求进⾏转发,重定向的功能。
@ComponentScan:这个就是组件扫描,对指定路径下将符合的bean实例化放入到IOC容器中,建议与@Configuration一起用。等下讲到。
@component:(把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>),泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。
获取User类的实例测试:
结果如下:
这就说明在@ComponentScan扫描的路径下,只要有注解@Component修饰的类就是被实例化到IOC容器中等待调用。
@Repository,@Service, @Controller都会被实例化。
4)、@Bean
加了@bean注解获取到了指定类的实例,但我们发现实例化不止一次。我们这次加上@Configuration
得出结论:
不配置@Confifiguration: 当内部method bean发⽣彼此依赖的时候会导致多例
@Confifiguration:
1.将@Confifiguration配置的Appconfifig由普通类型转变为cglib代理类型 单例
2.将AppConfifig的beanDefifinitioin属性赋值为full类型的(不配置的是lite)
5)、@Import
6)、ImportSelector
7)、ImportBeanDefinitionRegistrar
8)、@Conditional 条件注入 在springboot常用
2、bean的注册原理
将核心代码提取出来手动实现如上图
结果如下:
说明:1、xml配置有id 和name以id作为beanName为主
2、执行流程 创建一个注册器->创建bean定义读取器->获取资源(配置信息)->装载bean放入ioc容器中
================结束====================
下期进行spring IOC源码流程学习