Ioc&DI
Ioc
控制反转是一种设计思想 ,DI (依赖注入)是实现 IoC 的一种方法,也有人认为 DI 只是 IoC 的另一种说法。没有 IoC 的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。
什么是Ioc
Ioc
是指控制程序对象之间的关系、将对象的控制权由程序代码 转换到了外部容器当中。控制权的转移也叫控制反转(Ioc)。对于 Spring 而言,就是由 Spring 来控制对象的生命周期和对象之间的依赖关系。
什么是DI
Ioc
还有另外一个名字——“依赖注入。所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,由容器动态地将某种依赖关系注入到组件之中。
IOC的实现
- 引入依赖
<!-- 引入了SpringIOC的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
2.加载配置类
3.获得对象
xml实现
对象赋值
常见类型
Setter方法
<!--SpringIOC的容器,负责管理对象的-->
<!--
产生DemoA类的对象
bean:代表一个对象
ID:代表的是对象的名字
class:代表对象是那个类产生的
-->
<!--
DemoA a = new DemoA();
-->
<bean class="com.fzj.spring.ioc.xml.DemoA" id="a"/>
<!--产生对象属性并赋值-->
<!--Setter-->
<bean class="com.fzj.spring.ioc.xml.DemoA" id="b">
<!--给对象属性赋值 Setter方法-->
<!--
name:属性名
value:值
-->
<property name="id" value="1"/>
<property name="name">
<value>ff</value>
</property>
<property name="gender" value="男"/>
</bean>
构造器
` <!--一个参数的构造器-->
<bean class="com.fzj.spring.ioc.xml.DemoA" id="c1">
<!--
通过构造器赋值
constructor-arg:给某个属性赋值
value:值
index:第几个参数
name:参数名(和index作用一致)
-->
<constructor-arg value="1" index="0"/>
</bean>
<!--两个参数的构造器-->
<!--
通过构造器赋值
constructor-arg:给某个属性赋值
value:值
index:第几个参数
name:参数名(和index作用一致)
-->
<bean class="com.fzj.spring.ioc.xml.DemoA" id="c2">
<constructor-arg value="1" name="id"/>
<constructor-arg value="张三" index="1"/>
</bean>
<!--全参构造器-->
<bean class="com.fzj.spring.ioc.xml.DemoA" id="c3">
<constructor-arg name="id" value="1"/>
<constructor-arg index="1" value="李四"/>
<constructor-arg name="gender" value="男"/>
</bean>
数组集合类型
Setter方法
<!--setter方式-->
<bean class="com.fzj.spring.ioc.xml.DemoB" id="b1">
<property name="array">
<array>
<value>陕西</value>
<value>福建</value>
<value>广西</value>
</array>
</property>
<property name="list">
<list>
<value>西安</value>
<value>宝鸡</value>
<value>商洛</value>
</list>
</property>
<property name="set">
<set>
<value>足球</value>
<value>篮球</value>
<value>排球</value>
</set>
</property>
<property name="map">
<map>
<entry key="A" value="aa"/>
<entry key="B" value="bb"/>
</map>
</property>
</bean>
构造器
<!--构造器方式赋值-->
<bean class="com.fzj.spring.ioc.xml.DemoB" id="b2">
<constructor-arg index="0">
<array>
<value>陕西</value>
<value>福建</value>
<value>广西</value>
</array>
</constructor-arg>
<constructor-arg index="1">
<list>
<value>西安</value>
<value>宝鸡</value>
<value>商洛</value>
</list>
</constructor-arg>
<constructor-arg name="set">
<set>
<value>足球</value>
<value>篮球</value>
<value>排球</value>
</set>
</constructor-arg>
<constructor-arg name="map">
<map>
<entry key="A" value="aa"/>
<entry key="B" value="bb"/>
</map>
</constructor-arg>
</bean>
对象类型
Setter方法
<!--给自定义类型属性赋值-->
<bean class="com.fzj.spring.ioc.xml.DemoC" id="d1">
<!--通过使用 ref 标记指定 bean 属性的目标 bean-->
<property name="a" ref="a"/>
<property name="b" ref="b2"/>
</bean>
获取对象
byName
通过对象名获取 缺点是返回的类型是Object类型的需要自行强转
ApplicationContext c = new ClassPathXmlApplicationContext("applicationContext.xml");
//byName
Object a = c.getBean("b");
System.out.println(a);
byType
通过类型自动获取对象 缺点是 当容器中出现多个相同类型的对象时 无法自动匹配
//byType
DemoC c1 = c.getBean(DemoC.class);
System.out.println(c1);
byType+byName
通过类型+名字精准获取对象 缺点是写得多
//byTyp+byName
DemoA a1 = c.getBean("c2", DemoA.class);
System.out.println(a1);
加载Ioc容器方式
FileSystemXmlApplicationContext 实现方式
这种方式是以项目路径为相对路径的绝对起点 非maven项目
ApplicationContext bean = new FileSystemXmlApplicationContext("ioc/src/main/resources/applicationContext.xml");
ClassPathXmlApplicationContext实现方式
这种方式是以maven的resources 文件夹为相对路径起始点
ApplicationContext bean = new ClassPathXmlApplicationContext("applicationContext.xml");
XmlWebApplicationContext 实现方式
在 Web 环境下初始化监听器的时候会加载。很少使用
AnnotationConfigApplicationContext 实现方式
注解方法 零xml配置。根据注解的方式启动Spring容器
ApplicationContext bean = new AnnotationConfigApplicationContext("com.dailyblue.java.spring");
注解实现
产生对象
名称 | 功能 |
---|---|
@Component | 用于普通类、启动spring后,会自动把它转成容器管理的bean |
@Repository | 用于DAO层注解 功能同@Component |
@Service | 用于对业务层注解 功能同@Component |
@Controller | 用于对控制层注解 功能同@Component |
使用时如果没有自定义名字默认是类名首字母小写 使用value属性来自定义属性名
对象赋值
名称 | 功能 |
---|---|
@Autowired | 默认按照类型(byType)自动装配 缺点是当有多个相同类型时会出错 |
@Resource | byName(+byType):按照名称赋值,如果名称不存在,按照类型赋值 |
@Autowired @Qualifier(“a2”) | // 辅助@Autowired注解的使用,在byType基础上增加了byName功能 |
//赋值注解
@Autowired // byType:按照类型自动赋值
//byType
private DemoA a;
@Resource(name = "a2")//将对象名为a2的类赋值给a1
//byName(+byType) // byName(+byType):按照名称赋值,如果名称不存在,按照类型赋值
private DemoA a1;
@Autowired
@Qualifier("a2") // 辅助@Autowired注解的使用,在byType基础上增加了byName功能
private DemoA a3;
byName和byType区别
byName
是根据对象名来注入对象、缺点是返回的类型是Object类型 需要强转
byType
是跟据类型来自动注入对象 缺点是无法满足多个相同类型对象的场景 无法自动识别装配
@Autowired和@Resource的区别
相同:都是实现对象赋值的
不同:
@Autowired
按照所需类型自动装配的 在出现多个相同类型的对象时 无法自动识别装配
@Resource
默认按照名称赋值 如果名称不存在再按照类型赋值
设计模式
单例模式
一个类有一个对象
多例模式
一个类由多个对象
@Component
//设置当前类只产生一个对象(也是默认效果)
//@Scope(value = "singleton")
//每次获取当前类对象时 产生对象
@Scope(value = "prototype")
public class DemoC {
}
配置管理
配置类注解
@Configuration 声明为配置类 在加载资源时会从该类开始
//声明为配置类
@Configuration
public class SpringConfig {
}
手动扫描
配置扫描那些包,一次可以扫描多个包
@ComponentScan("com.fzj.spring.ioc.annotation.bean")
//扫描多个包的方式
//@ComponentScan(basePackages = {"com.fzj.spring.ioc.annotation.bean", "com.fzj.spring.ioc.annotation.config"})
手动产生对象并放到Ioc容器中
使用场景 使用别人开发的资源
@Configuration
@ComponentScan("com.fzj.spring.ioc.annotation.bean")
//扫描多个包的方式
//@ComponentScan(basePackages = {"com.fzj.spring.ioc.annotation.bean", "com.fzj.spring.ioc.annotation.config"})
public class SpringConfig {
//手动添加对象到Ioc容器中
@Bean
public DemoE getDemoE() {
return new DemoE();
}
}
SpringIoc中bean的生命周期
Bean的生命周期包括 bean的定义、bean的初始化、bean的使用、bean的销毁
Bean 的生命周期包括 Bean 的定义,Bean 的初始化,Bean 的使用,Bean 的销毁。
Bean 的定义:一般 Bean 使用 XML 文件的方式进行定义,定义的时候将 Bean 之间的依赖关系和属性的赋值都进行了定义。
Bean 的初始化:其实 Bean 的初始化包括 Bean 的创建和初始化两个方法,Bean 的创建和初始化一般是同步进行的,Bean 在完成创建后直接就会进行初始化操作,创建的时机与 Bean 的 lazy-init 属性的设置有关。
Bean 的使用:在 web 程序运行期间,发生对某一个 Bean 的调用时,就会使用这个 Bean实例,如果使用编码的方式来获取 Bean 同样也是 Bean 的使用,Bean 的编码使用方式有三种,第一种是使用 BeanWarpper,第二种是使用 BeanFactory,第三种就是使用 ApplicationContext。
Bean 的销毁:Bean 实例在程序退出的时候会进行销毁,而在销毁之前会自动调用 Bean的 destory-method 属性指定名称的方法。
Bean的定义:
xml方式
<bean class="com.fzj.spring.ioc.xml.DemoA" id="a"/>
注解方式
使用 @Component
@Controller
@Repository
@Service
四种注解添加到类上时
bean的创建和初始化
bean的创建及初始化默认在加载配置文件时
bean的使用
xml方式在使用byName 、byType等时候
注解方式 在使用 @Autowired
@Resource
等
bean的销毁
Bean 实例在程序退出的时候会进行销毁,而在销毁之前会自动调用 Bean的 destory-method 属性指定名称的方法。
IoC管理对象的创建
勤加载
默认情况,当启动IoC容器时,加载创建XML或者注解中的对象。
懒加载
当启动IoC容器时,不创建XML或者注解中的对象。只有在使用时才创建。