1, IOC概念和原理
1)什么是IOC?
- 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。
- 使用IOC目的,为了耦合度降低。
- 做入门案例就是IOC实现。
2)IOC底层原理
- xml解析,工厂模式,反射
3)IOC(接口)
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。
- Spring提供IOC容器实现两种方式:(两个接口)
- BeanFactory: IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用。
注:加载配置文件的时候不会创建对象,而在获取对象的时候才去创建对象 - ApplicationContext:BeanFactory接口的子接口,提供更多强大的功能,一般由开发人员进行使用。
注:加载配置文件的时候就可以创建对象
- BeanFactory: IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用。
2,IOC容器-Bean管理XML方式— 注入(Injection)
2.1, 什么是注入
1,通过Spring工厂及配置文件,为所创建对象的成员变量赋值。
2.2, 为什么需要注入?
1,通过编码的方式,为成员变量进行赋值,存在耦合
public static void test6(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
User user = ctx.getBean("User", User.class);
//以下代码存在耦合
user.setAge(4);
user.setName("夏木");
}
2.3, 如何进行注入【开发步骤】
- 类为成员变量提供set, get方法
- 配置Spring的配置文件
<bean id="User" name="U,u" class="User">
<property name="age">
<value>12</value>
</property>
<property name="name">
<value>王八犊子</value>
</property>
</bean>
SpringFactory
public static void test7(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
User user = ctx.getBean("User", User.class);
System.out.println("user = " + user);
}
2.4, 注入好处
1, 解耦合
3,创建对象和set的方式注入属性
3.1,针对不同类型的成员变量,在标签,需要嵌套其他标签
1) 八种基本类型:
<property name="property"></property>
2) 数组或List集合
<property name="property">
<list>
<value></value>或其他
</list>
</property>
3) Set集合
<property name="proterty">
<set>
<value></value>或者<bean id="id" Class="classPath"/> 或者其他
</set>
</property>
4) Map集合
<property name="proterty">
<map>
<entry>
<key><value> key </value></key>
<value> value </value>
</entry>
</map>
</property>
5) properties类型
<property name="proterty">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
</props>
</property>
6) 复杂JDK类型
需要程序员自定义类型转换器。。。`
7)用户自定义类型
<bean id="userDao" class="XXX.userDaoImpl"/>
<bean id="userService" class="XXX.userServiceImpl">
<property name="userDao"><ref bean="userDao"/></property>
</bean>
简化:
<bean id="userDao" class="XXX.userDaoImpl"/>
`
<bean id="userService" class="XXX.userServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
3.2,基于P命名空间简化
1)JDK类型注入
<bean id="XXX" class="XXX" p:name="张三"/>
2)自定义类型注入
<bean id="userDao" class="userDaoImpl"/>
<bean id="userService" class="userServiceImpl" p:userDao-ref="userDao"/>
注意:这里只能简化八种基本类型和用户自定义类型
4,有参构造注入属性
<bean id="user" class="com.company.Spring.User">
<constructor-arg name="name" value="小光"></constructor-arg>
<constructor-arg name="age" value="12"></constructor-arg>
</bean>
另一种写法:
<bean id="user" class="com.company.Spring.User">
<constructor-arg index="0" value="小光"></constructor-arg>
<constructor-arg index="1" value="12"></constructor-arg>
</bean>
5,注入空值和特殊符号
- 注入空值
<property name="property">
<null/>
</property>
- 特殊符号
- 把特殊符号进行转义, 例如:
< >
- 把带特殊符号内容写到CDTAT
- 把特殊符号进行转义, 例如:
<property name="property">
<value><![CDATA[含特殊符号的内容]]></value>
</property>
6,注入外部bean
(1)创建两个Service类和dao类
(2)在service调用dao里面的方法
(3)在spring配置文件中进行配置
bean1.xml文件中
<bean id="userService" class="com.company.UserService">
<property name="userDao" ref="userDaoImpl">
</property>
</bean>
<bean id="userDaoImpl" class="com.company.UserDaoImpl"></bean>
6,注入内部bean和级联赋值
- 注入内部bean
(以员工和部门为例子)
(1)一对多关系,部门和员工
(2)在实体类之间表示一对多关系
部门类
package com.company.test;
public class Dept {
private String dname;
public void setDname(String dname){
this.dname = dname;
}
public String getDname() {
return dname;
}
}
员工类
package com.company.test;
public class Emp {
private String ename;
private String gender;
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setEname(String ename) {
this.ename = ename;
}
public Dept getDept() {
return dept;
}
public String getEname() {
return ename;
}
public String getGender() {
return gender;
}
}
bean.xml文件
<bean id="emp" class="com.company.test.Emp">
<property name="ename" value="张三"></property>
<property name="gender" value="男"></property>
<property name="dept">
<bean id="dept" class="com.company.test.Dept">
<property name="dname" value="保安部"></property>
</bean>
</property>
</bean>
- 级联赋值
(只需更改bean.xml文件)
<bean id="emp" class="com.company.test.Emp">
<property name="ename" value="张三"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="dept"/>
</bean>
<bean id="dept" class="com.company.test.Dept">
<property name="dname" value="保安部"></property>
</bean>
7,工厂bean
- Spring有两种类型bean, 一种普通bean,另为一种工厂bean(FactoryBean)
- 普通bean:在配置文件中定义bean类型就是返回类型
- 工厂bean: 在配置文件中定义bean类型可以与返回值类型不一样
- 第一步创建类,让这个类作为工厂bean,实现接口FactoryBean
- 第二步实现接口里面的方法,在实现的方法中定义返回的bean类型
8, bean的作用域
- 在Spring里面,设置创建bean实例是默认单实例对象
- 设置多实例对象的方法:
- 在Spring配置文件bean标签里面有属性(scope) 用于设置单实例还是多实例
- scope属性值 :第一个值为singleton, 表示单实例对象,第二个值为prototype,表示多实例对象
- singleton和prototype区别
- singleton 单实例,prototype多实例
- 设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象
- 设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象
9,bean的生命周期
1,生命周期: 从对象创建到对象销毁的过程。
2,bean的生命周期
(1)通过构造器创建bean实例(无参构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)把bean实例传递bean后置处理器的方法
(4)调用bean的初始化的方法(需要配置方法)
(5)把bean实例传递bean后置处理器的方法
(6)bean可以使用了(对象获取到了)
(7)当容器关闭时候,调用bean的销毁方法(需要配置方法)
1) 配置初始化方法
Student类中添加
public void initmethod(){
System.out.println("初始化");
}
XML文件中设置init-method属性
<bean id="student" class="com.company.test.Student" init-method="initmethod"/>
2)配置销毁方法
Student类中添加
public void destorymethod(){
System.out.println("销毁对象");
}
XML文件中设置init-method属性
<bean id="student" class="com.company.test.Student" destroy-method="destroyMethod"/>
测试
@Test
public void test(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml");
Object obj = ctx.getBean("student", Student.class);
System.out.println(obj.toString());
ctx.close();
System.out.println("对象已销毁");
}
3)实现后置处理器
XML
10,XML实现自动装配
(该方法不常用)
配置XML文件
<!--实现自动装配
bean标签属性autowire, 配置自动装配
autowire属性常用两个值:
byName根据属性名字注入,注入值bean的id值和类属性名称一样
byType根据属性类型注入
-->
<bean id="emp" class="com.company.autoWrie.Emp" autowire="byName">
<!--<property name="dept" ref="dept"></property>-->
</bean>
Java文件
package com.company.autoWrie;
public class Emp {
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
11,外部文件属性
- 直接配置数据库信息
- 配置德鲁伊连接池
- 引入德鲁伊连接池依赖或jar包
如图:
配置XML文件
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/StudentSystem"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
- 引入外部属性文件配置数据库连接池
- 配置properties文件
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/StudentSystem
prop.userName=root
prop.password=123456
- 把外部properties属性文件引入到spring配置文件中
<!-- 引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>