spring-ioc
目录
ioc概述
IoC 是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移就是所谓反转。对于 Spring 而言,就是由 Spring 来控制对象的生命周期和对象之间的依赖关系。IoC 还有另外一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,即由容器动态地将某种依赖关系注入到组件之中。
ioc的理解过程
最初的JDBC形式,不直观,硬编码!
为了解耦,分为三层架构:
controller:控制层
service:业务层
dao:数据层
分层解耦
思想理解——由于new对象的高耦合,不利解码以及维护,我们会采用spring中的 IOC 思想
在IOC容器里统一管理bean对象,相当于new对象。
具体思想流程案例:
ioc 容器的规范
IoC 容器有两种规范:BeanFactory 和 ApplicationContext。
BeanFactory:BeanFactory 为 IOC 容器提供了基础功能,Spring 文档中提到,当前该类仅仅是为了向后兼容老的版本,除非你有更好的原因否则就应该使用第二种容器。
ApplicationContext:通过 API 文档可以知道,ApplicationContext 是BeanFactory 的子接口,并且从文档中也可以看到 ApplicaionContext 除了包含有 BeanFactory 的所有功能还支持了更多的功能。
BeanFactory 和 ApplicationContext 多是接口,都是对 IoC 容器提出了规范,对于它们而言是通过对应的实现类去实现,分别有四种实现方式。
创建bean对象
xml形式创建
在 applicationContext.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">
<!--管理对象-->
<!--
产生对象
DemoA a = new DemoA();
-->
<bean id="a" class="com.dailyblue.java.spring.ioc.before.xml.DemoA"/>
<bean id="b" class="com.dailyblue.java.spring.ioc.before.xml.DemoB">
<property name="name" >
<value>展示</value>
</property>
<property name="gender" value="男"></property>
<property name="weight" value="100"></property>
<property name="id" value="1"></property>
</bean>
<bean id="c" class="com.dailyblue.java.spring.ioc.before.xml.DemoC">
<property name="a">
<array>
<value>aa</value>
<value>bb</value>
<value>cc</value>
<value>aa</value>
</array>
</property>
<property name="b">
<list>
<value>西安</value>
<value>渭南</value>
<value>铜川</value>
<value>西安</value>
</list>
</property>
<property name="c">
<set>
<value>西安</value>
<value>渭南</value>
<value>铜川</value>
<value>西安</value>
</set>
</property>
<property name="d">
<map>
<entry key="A" value="aa"/>
<entry key="B" value="bb"/>
<entry key="C" value="cc"/>
</map>
</property>
</bean>
<bean id="d" class="com.dailyblue.java.spring.ioc.before.xml.DemoD">
<property name="a" ref="a"/>
<property name="b" ref="b"/>
<property name="c" ref="c"/>
</bean>
<!--通过构造器给属性赋值-->
<bean id="e1" class="com.dailyblue.java.spring.ioc.before.xml.DemoE">
<!--
constructor-arg:构造器赋值
index:索引号
name:参数名
value:值
ref:值
type:参数数据类型
-->
<constructor-arg name="id" value="101" type="java.lang.Integer"/>
<constructor-arg index="1" value="李思"/>
<constructor-arg index="2">
<array>
<value>足球</value>
<value>烂球</value>
</array>
</constructor-arg>
<constructor-arg index="3" ref="b"/>
<constructor-arg index="4" ref="d"/>
</bean>
<bean id="e2" class="com.dailyblue.java.spring.ioc.before.xml.DemoE">
<constructor-arg index="0" value="2"/>
<constructor-arg index="1" value="李四"/>
<constructor-arg index="2">
<array>
<value>排球</value>
</array>
</constructor-arg>
</bean>
<!--懒加载和勤加载-->
<bean id="f" class="com.dailyblue.java.spring.ioc.before.xml.DemoF" lazy-init="true"/>
<bean id="grade" class="com.dailyblue.java.spring.ioc.before.xml.work.work01.Grade">
<property name="name" value="四班"/>
<property name="students" >
<list>
<ref bean="student1"/>
<ref bean="student2"/>
<ref bean="student3"/>
</list>
</property>
</bean>
<bean id="student1" class="com.dailyblue.java.spring.ioc.before.xml.work.work01.Student">
<property name="studentId" value="01"/>
<property name="name" value="张三"/>
<property name="gender" value="男"/>
</bean>
<bean id="student2" class="com.dailyblue.java.spring.ioc.before.xml.work.work01.Student">
<property name="studentId" value="02"/>
<property name="name" value="李四"/>
<property name="gender" value="女"/>
</bean>
<bean id="student3" class="com.dailyblue.java.spring.ioc.before.xml.work.work01.Student">
<property name="studentId" value="03"/>
<property name="name" value="王五"/>
<property name="gender" value="男"/>
</bean>
</beans>
常见标签 API
<bean> 标签:每一个标签 bean 对应的就一个类对象,通过 id(或者Name)以及 Class 来定位一个类,这边 Class 要求是完全限定类名。
id | 对象名 |
name | 等同于 id,用于指定 bean 的别名 |
class | 对象的完整类路径 |
lazy-init | 用于指定当前 Bean 的初始化时间 若值为 true 表示在初次调用时才会自动创建实例并初始化 false 表示在 IoC 容器创建的时候就会完成 创建和初始化 |
init-method | 用于指定当前 Bean 的初始化方法,在 Bean 实例创建好后,首先会调 用其指定名称的方法 |
destory-method | 用于指定当前 Bean 的销毁方法,在 Bean 即将被销毁之前会自动调用 该属性指定的方法 |
depends-on | 用于指定当前 Bean 的依赖 Bean,强制指定的 Bean 在当前 Bean 初 始化之前先完成初始化 |
abstract | 代表是否是抽象类,值:true|false |
scope | 生命周期作用域: singleton:默认的,单例模式 prototype:多例模式 request:一个 bean 定义作用于 HTTP 的 Request 生命周期;是指每个 HTTP 的 Request 拥有自己的通过一个 bean 定义创建的实例。 仅在 web 中有效 session:一个 bean 定义作用于 HTTP 的 Session 生命周期;是指每 个 HTTP 的 Session 拥有自己的通过一个 bean 定义创建的实例。仅 在 web 中有效 |
注解创建
@Component | 启动 Spring 后,会自动把它转成容器管理的 Bean |
@Repository | 用于对DAO层注解,但是目前该功能与 @Component 相同 |
@Service | 用于对业务层注解,但是目前该功能与 @Component 相同 |
@Controller | 用于对控制层注解,但是目前该功能与 @Component 相同 |
获取对象
getBean 获取对象
从容器中获取对象,我们主要由三种方式
- byName:根据名字获取
- byType:根据类型获取
- byName+byType:根据名字和类型获取
具体实现:
// byName 根据名称获取对象,缺点是返回结果是Object类型的,需要自行强转
Object obj1 = beans.getBean("db");
// byType 根据类型获取对象,缺点是容器中只能有一个DemoB类型的对象
DemoB obj2 = beans.getBean(DemoB.class);
// byName+byType:根据名称和类型获取,缺点是写得多
DemoB obj3 = beans.getBean("db", DemoB.class);
bean的声明的具体规则:
扫描bean对象的范围
具体问题分析:
相同类型,不同名称的bean对象 如何解决?