SpringIOC
1 概念
spring 不是一个功能性框架 一种设计层面的框架
spring核心:ioc和aop
IOC:控制反转 Inversion of Control
spring把程序所依赖所有对象的创建、初始化、分配、管理、销毁等工作交给spring容器
对象的所有控制权交给了spring容器 而不再是由程序做主
DI:依赖注入Dependency injection
在运行时期 spring容器把程序依赖的对象动态的注入到程序中
2 ioc案例1
创建java项目
导入jar包
logging-1.1.1.jar:日志jar
log4j-1.2.15.jar:日志jar
asm-3.0.1.RELEASE-A.jar:字节码文件解析jar
RELEASE-A.jar:javabean实体类依赖的jar
context-3.0.1.RELEASE-A.jar:spring功能控制jar---验证/jmail
core-3.0.1.RELEASE-A.jar:springioc核心jar
expression-3.0.1.RELEASE-A.jar:spring表达式依赖的jar
创建srping的核心配置文件
spring_ioc_core.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- xsd文件对当前xml文件进行语法检查 :规定有哪些标签 有哪些属性 标签的嵌套关系-->
</beans>
创建实体类
public class Student {
private Integer sid;
private String sname;
private String sex;
private Integer sage;
private Boolean sdy;
...
}
在核心配置文件中通过bean标签来创建对象
<!-- 通过bean标签创建程序依赖的对象 -->
<!-- Integer sid, String sname, String sex, Integer sage, Boolean sdy -->
<bean name="s1" class="com.zhiyou100.ioc.day01.Student">
<property name="sid" value="1001"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
</bean>
<bean name="s2" class="com.zhiyou100.ioc.day01.Student">
<constructor-arg index="0" value="1002" />
<constructor-arg index="2" value="韩红" />
<constructor-arg index="1" value="女" />
<constructor-arg index="4" value="false" />
<constructor-arg index="3" value="33" />
</bean>
测试类
//创建spring上下文对象 关联核心配置文件
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/zhiyou100/ioc/day01/spring_ioc_core_01.xml");
//通过上下文对象的getbean方法 由bean的name值获取javabean对象
Student stu1=(Student)context.getBean("s1");
System.out.println(stu1);
Student stu2=(Student)context.getBean("s2");
System.out.println(stu2);
context.close();
3 研究springioc
3.1spring创建bean的特点
1:默认情况下 项目启动:spring容器读取核心配置文件 就创建bean标签对应的javabean对象
2:spring中bean标签是单例对象:一个bean标签默认只创建一个对象
同一个bean标签调用多次 创建的是同一个对象
3:默认调用实体类的无参数的构造方法创建对象:如果没有无参数的构造方法:抛出异常:NoSuchMethodException
4:如果bean标签中是property标签:javabean通过set方法给属性赋值
如果bean标签中是constructor-arg标签:javabean通过构造方法参数列表给属性赋值
3.2获取springcontent的方式
//创建spring上下文对象 关联核心配置文件
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/zhiyou100/ioc/day01/spring_ioc_core_01.xml");
//通过上下文对象的getbean方法 由bean的name值获取javabean对象
Student stu1=(Student)context.getBean("s1");
System.out.println(stu1);
context.close();
//创建spring上下文对象方式2:FileSystemXmlApplicationContext
FileSystemXmlApplicationContext context2=new FileSystemXmlApplicationContext("src/com/zhiyou100/ioc/day01/spring_ioc_core_01.xml");
Student stu4=(Student)context2.getBean("s1");
System.out.println(stu4);
context.close();
3.3多个核心配置文件
- 方式1:ClassPathXmlApplicationContext的参数是不定参数 可以指定多个配置文件的路径
//多个spring核心配置文件
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/zhiyou100/ioc/day01/spring_ioc_core_01.xml","com/zhiyou100/ioc/day01/spring_ioc_core_02.xml");
- 方式2:在主配置文件中通过import标签引入所有的其他配置文件
<import resource="spring_ioc_core_02.xml"/><!-- 相对于当前配置文件的目录 -->
3.4 给属性赋值方式
- 通过set方法给属性赋值:调用的property标签
<bean name="s1" class="com.zhiyou100.ioc.day01.Student">
<property name="sid" value="1001"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
</bean>
- 通过构造方法参数列表给属性赋值:调用constructor-arg标签
<bean name="s1" class="com.zhiyou100.ioc.day01.Student">
<constructor-arg index="0" value="1002" />
<constructor-arg index="2" value="韩红" />
<constructor-arg index="1" value="女" />
<constructor-arg index="4" value="false" />
<constructor-arg index="3" value="33" />
</bean>
3.5 bean关联
- 实体类Teacher
public class Teacher implements Serializable{//注意实现序列化
private Integer tid;
private String tname;
private String tsex;
...
}
- 实体类Student
public class Student implements Serializable{
private Integer sid;
private String sname;
private String sex;
private Integer sage;
private Boolean sdy;
//定义引用记录当前学生的老师
private Teacher teacher;
...
}
- 配置bean
<bean name="s1" class="com.zhiyou100.ioc.day02.Student">
<property name="sid" value="1001"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
<!-- 给teacher属性赋值:private Teacher teacher -->
<!-- property和constructor-arg标签的value属性:给单值数据(基本数据类型+字符串)赋值 -->
<!-- property和constructor-arg标签的ref属性:给引用类型数据(对象类型)赋值 -->
<property name="teacher" ref="t1"/>
</bean>
<bean name="t1" class="com.zhiyou100.ioc.day02.Teacher">
<property name="tid" value="1"/>
<property name="tname" value="张老师"/>
<property name="tsex" value="男"/>
</bean>
3.6 bean作用域
<!-- bean的作用域:通过scope属性制定 -->
<!-- scope属性的值:
singleton:单例 每次调用此bean获取的永远是同一个对象 (默认)
prototype:多例 每次调用bean 获取都是新的对象
request: 适用于web项目:同一个请求链 调用同一个bean获取的是同一个对象
session: 适用于web项目:同一个回话 调用同一个bean获取的是同一个对象
global-session: 适用于web项目:同一个servletcontext 调用同一个bean获取的是同一个对象
-->
<bean name="s2" class="com.zhiyou100.ioc.day02.Student" scope="prototype">
<property name="sid" value="1001"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
</bean>
3.7 bean懒加载
<!-- bean的懒加载:默认情况下scope=singleton的bean 项目启动spring容器加载核心配置文件就会创建bean对应的对象
开头通过lazy-init="true"属性来指定 bean标签第一次被调用时才创建对象
-->
<bean name="s3" class="com.zhiyou100.ioc.day02.Student" scope="singleton" lazy-init="true">
<property name="sid" value="1003"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
</bean>
3.8 bean生命周期
对象创建 对象初始化 对象调用 对象销毁
- 实体类Student
public class Student implements Serializable{
public void init(){
System.out.println("初始化方法:++++++:public void init()");
}
public void destory(){
System.out.println("销毁方法::------:public void destory()");
}
。。。
}
- bean配置
<!-- bean的生命周期:
bean对象创建完后会立刻调用init-method属性对应的方法进行对象的初始化
springcontext关闭之前会调用destroy-method属性对应的方法进行对象的销毁
-->
<bean name="s4" class="com.zhiyou100.ioc.day02.Student" init-method="init" destroy-method="destory">
<property name="sid" value="1003"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
</bean>
3.9 bean的集合属性
- 实体类
public class Worker implements Serializable{
private Integer wid;
private Teacher teacher;
private int[] arrInt;
private Teacher[] arrTea;
private List<Teacher> listTea;
private List<Integer> listInt;
private Set<Integer> setInt;
private Map<String, Teacher> map;
...
}
- 配置文件
<!-- 集合类型的属性-->
<bean name="tea1" class="com.zhiyou100.ioc.day02.Teacher">
<property name="tid" value="11"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="男"/>
</bean>
<bean name="tea2" class="com.zhiyou100.ioc.day02.Teacher">
<property name="tid" value="12"/>
<property name="tname" value="田老师"/>
<property name="tsex" value="男"/>
</bean>
<bean name="tea3" class="com.zhiyou100.ioc.day02.Teacher">
<property name="tid" value="13"/>
<property name="tname" value="陈老师"/>
<property name="tsex" value="女"/>
</bean>
<bean name="w1" class="com.zhiyou100.ioc.day02.Worker">
<!-- private Integer wid; -->
<property name="wid" value="1001"/>
<!-- private Teacher teacher; -->
<property name="teacher" ref="tea1"/>
<!-- private int[] arrInt; -->
<property name="arrInt">
<array value-type="int">
<value>111</value>
<value>112</value>
<value>113</value>
<value>114</value>
</array>
</property>
<!-- private Teacher[] arrTea; -->
<property name="arrTea">
<array value-type="com.zhiyou100.ioc.day02.Teacher">
<ref bean="tea1"/>
<ref bean="tea2"/>
<ref bean="tea3"/>
</array>
</property>
<!-- private List<Teacher> listTea; -->
<property name="listTea">
<list value-type="com.zhiyou100.ioc.day02.Teacher">
<ref bean="tea1"/>
<ref bean="tea2"/>
<ref bean="tea3"/>
<ref bean="tea1"/>
<ref bean="tea2"/>
<ref bean="tea3"/>
</list>
</property>
<!-- private List<Integer> listInt; -->
<property name="listInt">
<list value-type="java.lang.Integer">
<value>21</value>
<value>31</value>
<value>41</value>
</list>
</property>
<!-- private Set<Integer> setInt; -->
<property name="setInt">
<set value-type="java.lang.Integer">
<value>22</value>
<value>32</value>
<value>42</value>
<value>22</value>
<value>32</value>
<value>42</value>
</set>
</property>
<!-- private Map<String, Teacher> map; -->
<property name="map">
<map key-type="java.lang.String" value-type="com.zhiyou100.ioc.day02.Teacher">
<entry key="key1" value-ref="tea1"/>
<entry key="key2" value-ref="tea2"/>
<entry key="key3" value-ref="tea3"/>
</map>
</property>
</bean>
3.10 工厂模式
目标对象的创建 由factory类的方法来实现
实例工厂模式:提供创建目标对象的工厂方法是实例方法
- 实例工厂类
public class FactoryInstance implements Serializable{
public Teacher getInstance(){
Teacher t=new Teacher();t.setTid(1);t.setTname("韩梅梅");t.setTsex("女");
return t;
}
}
- 配置
<!-- 实例工厂模式 -->
<!-- 创建bean:获取实例工厂对象 -->
<bean name="factoryInstance" class="com.zhiyou100.ioc.day02.FactoryInstance"/>
<!-- 创建bean:调用实例工厂对象的方法获取目标对象 -->
<bean name="tea01" factory-bean="factoryInstance" factory-method="getInstance"/>
静态工厂模式:提供创建目标对象的工厂方法是静态方法
- 静态工厂类
public class FactoryStatic implements Serializable{
public static Teacher getInstance(){
Teacher t=new Teacher();t.setTid(1);t.setTname("韩梅梅");t.setTsex("女");
return t;
}
}
- 配置
<!-- 静态工厂模式 -->
<bean name="tea02" factory-method="getInstance" class="com.zhiyou100.ioc.day02.FactoryStatic" />
3.11 自动装配:自动关联对象的属性赋值
- 实体类
public class Student {
private Integer sid;
private String sname;
private String sex;
private Integer sage;
private Boolean sdy;
private Teacher teacher;
...
}
- 配置
<!-- autowire="byName":自动给对象类型的属性赋值:bean名字和属性名一致 -->
<bean name="s2" class="com.zhiyou100.ioc.day03.Student" autowire="byName">
<property name="sid" value="1003"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
<!-- private Teacher teacher; -->
</bean>
<!-- autowire="byType":如果找到一个指定类型的bean 直接赋值
如果找到多个 赋值bean的名字与属性名相同的
如果找到多个 但没有bean的名字与属性名字相同的 报错:UnsatisfiedDependencyException
-->
<bean name="s3" class="com.zhiyou100.ioc.day03.Student" autowire="byType">
<property name="sid" value="1003"/>
<property name="sex" value="男"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="23"/>
<property name="sdy" value="true"/>
<!-- private Teacher teacher; -->
</bean>
4 注解形式的ioc
4.1 导入jar
注解的jar和配置的jar完全一样
4.2 在核心配置文件中引入context的命名空间和xsd
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--命名空间和xsd文件都是复制修改的-->
</beans>
4.3 使用context标签指定添加了注解的实体类的位置
<!-- 添加标签指定添加注解的实体类位置 -->
<context:component-scan base-package="com.zhiyou100.ioc.day04"/>
4.4 在实体类上添加注解
package com.zhiyou100.ioc.day04;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.jws.soap.InitParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
//@Repository //创建bean的注解:给dao持久层的类添加的注解
//@Controller //创建bean的注解:给controller控制层的类添加的注解
//@Service //创建bean的注解:给service业务层的类添加的注解
@Component("s2") //创建bean的注解:不确定当前bean具体属于那一层 可以加属性:用于指定bean的名字 不加默认是类名首字母小写
//@Scope("prototype") //指定bean的作用域
@Lazy//懒加载 只适用于单例模式
public class Student {
{
System.out.println("构造代码块!!");
}
//@Value("1001")给属性赋值:可以加载属性上 也可以加在set方法上
@Value("1001")
private Integer sid;
@Value("韩庚")
private String sname;
@Value("男")
private String sex;
@Value("19")
private Integer sage;
private Boolean sdy;
//@Autowired //自动装配:策略和byType类似
//@Resource(name="teacher")//自动装配:name指定bean的名字
@Resource
private Teacher teacher;
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getSage() {
return sage;
}
public void setSage(Integer sage) {
this.sage = sage;
}
public Boolean getSdy() {
return sdy;
}
@Value("true")
public void setSdy(Boolean sdy) {
this.sdy = sdy;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", sex=" + sex + ", sage=" + sage + ", sdy=" + sdy
+ ", teacher=" + teacher + "]";
}
public Student(Integer sid, String sname, String sex, Integer sage, Boolean sdy) {
super();
this.sid = sid;
this.sname = sname;
this.sex = sex;
this.sage = sage;
this.sdy = sdy;
}
public Student() {
super();
}
@PostConstruct
public void initMethod(){
System.out.println("public void initMethod()");
}
@PreDestroy
public void destroyMethod(){
System.out.println("public void destroyMethod()");
}
}