1 概念
框架:大师写好的半成品
spring框架:不是功能性框架(不属于某一层) 用于整合其他功能框架的中间层框架
核心:ioc和aop
ioc:Inversion of Control,控制反转
把程序中需要对象的创建 初始化 维护 分配 销毁等交给spring容器来管理
程序中需要的所有对象 不需要new 而是从spring容器中拿
di: Dependency Injection,依赖注入
在运行时 把需要的对象动态的注入到程序中
2 案例1
2.1 导入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
2.2 创建核心配置文件
spring_config.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">
</beans>xxxxxxxxxx spring_config.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"> </beans>xml
2.3 创建实体类
1 实现序列化
2 所有属性私有化:提供getset方法
3 提供无参数的构造方法
4 属性包装类类型
public class Student implements Serializable{
private Integer sid;
private String sname;
private Integer sage;
private Boolean sdy;
private Float score;
...
}
2.4 在核心配置文件中通过bean标签来创建对象
<bean id="stu1" class="com.zhiyou100.test01.Student">
<property name="sid" value="1001"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="19"/>
<property name="sdy" value="true"/>
<property name="score" value="11.6"/>
</bean>
<bean id="stu2" class="com.zhiyou100.test01.Student">
<constructor-arg name="sid" value="1002"/>
<constructor-arg name="sname" value="韩寒"/>
<constructor-arg name="sage" value="19"/>
<constructor-arg name="sdy" value="false"/>
<constructor-arg name="score" value="33.5"/>
</bean>
<bean id="stu3" class="com.zhiyou100.test01.Student">
<constructor-arg index="0" value="1003"/>
<constructor-arg index="1" value="韩非子"/>
<constructor-arg index="2" value="29"/>
<constructor-arg index="3" value="false"/>
<constructor-arg index="4" value="35.5"/>
</bean>
2.5 测试类
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("com/zhiyou100/test01/spring_config.xml");
Student s1=(Student)context.getBean("stu1");
System.out.println(s1);
Student s2=(Student)context.getBean("stu2");
System.out.println(s2);
Student s3=(Student)context.getBean("stu3");
System.out.println(s3);
context.close();
2.6 结果
3 注意事项
1:默认情况下:项目一启动,springcontext上下文对象就加载核心配置文件 立刻为每个bean标签创建对象
2:默认情况下:一个bean标签只对应一个对象:每个bean都是一个单例对象
3:property标签给属性赋值:必须提供无参数的构造方法:否则报错:NoSuchMethodException
对象创建后 提供调用set方法给属性赋值
4:constructor-arg标签给属性赋值:调用对应的构造方法 通过构造方法的参数列表给属性赋值
4 上下文对象的创建
ClassPathXmlApplicationContext context1=
new ClassPathXmlApplicationContext("com/zhiyou100/test01/spring_config.xml");
Student s11=(Student)context1.getBean("stu1");
System.out.println(s11);
context1.close();
FileSystemXmlApplicationContext context2=
new FileSystemXmlApplicationContext("src/com/zhiyou100/test01/spring_config.xml");
Student s12=(Student)context2.getBean("stu1");
System.out.println(s12);
context2.close();
5 多核心配置文件
5.1 方式1:ClassPathXmlApplicationContext构造方法是不定参数
ClassPathXmlApplicationContext context1=
new ClassPathXmlApplicationContext("com/zhiyou100/test01/spring_config01.xml","com/zhiyou100/test01/spring_config02.xml");
Student s11=(Student)context1.getBean("stu1");
System.out.println(s11);
Student s12=(Student)context1.getBean("stu2");
System.out.println(s12);
context1.close();
5.2 方式2:定义一个总的配置文件:通过import引入其他配置文件
<import resource="spring_config01.xml"/>
<import resource="spring_config02.xml"/>
- 创建ClassPathXmlApplicationContext只需要加载总的核心配置文件即可
ClassPathXmlApplicationContext context2=
new ClassPathXmlApplicationContext("com/zhiyou100/test01/spring_config03.xml");
Student s111=(Student)context2.getBean("stu1");
System.out.println(s111);
Student s122=(Student)context2.getBean("stu2");
System.out.println(s122);
context1.close();
6 对象关联
6.1 创建teacher类
public class Teacher implements Serializable{
private Integer tid;
private String tname;
private String tsex;
...
}
6.2 在student类中定义引用指向其关联的teacher对象
public class Student implements Serializable{
...
private Teacher teacher;
...
}
6.3 在核心配置文件中为teacher定义bean 并在student的bean中通过ref来关联此对象
<bean id="stu1" class="com.zhiyou100.test01.Student">
<property name="sid" value="1001"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="19"/>
<property name="sdy" value="true"/>
<property name="score" value="11.6"/>
<property name="teacher" ref="tea1"/>
</bean>
<bean id="tea1" class="com.zhiyou100.test01.Teacher">
<property name="tid" value="1"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
<bean id="stu2" class="com.zhiyou100.test01.Student">
<constructor-arg index="0" value="1003"/>
<constructor-arg index="1" value="韩非子"/>
<constructor-arg index="2" value="29"/>
<constructor-arg index="3" value="false"/>
<constructor-arg index="4" value="35.5"/>
<constructor-arg index="5" ref="tea1"/>
</bean>
6.4 测试
ClassPathXmlApplicationContext context2=
new ClassPathXmlApplicationContext("com/zhiyou100/test01/spring_config04.xml");
Student s111=(Student)context2.getBean("stu1");
System.out.println(s111);
Student s1112=(Student)context2.getBean("stu2");
System.out.println(s1112);
context2.close();
7 bean的作用域
<bean id="tea1" class="com.zhiyou100.test02.Teacher" scope="singleton">
<property name="tid" value="1"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
<bean id="tea2" class="com.zhiyou100.test02.Teacher" scope="prototype">
<property name="tid" value="2"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
8 bean的懒加载
<bean id="tea1" class="com.zhiyou100.test02.Teacher" scope="singleton">
<property name="tid" value="1"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
<bean id="tea2" class="com.zhiyou100.test02.Teacher" scope="singleton" lazy-init="true">
<property name="tid" value="2"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
9 工厂模式
工厂模式:a对象的创建 交给b工厂对象的方法来实现
9.1 静态工厂模式::工厂对象的方法是静态方法
public class TeacherFactoryStatic {
public static Teacher getInstance(){
return new Teacher(1001, "韩雪", "女");
}
}
<bean id="tea1" class="com.zhiyou100.test02.TeacherFactoryStatic" factory-method="getInstance" />
9.2 实例工厂模式::工厂对象的方法是实例方法
public class TeacherFactoryInstance {
public Teacher getInstance(){
return new Teacher(1001, "韩雪", "女");
}
}
- 配置文件中先创建工厂bean 在提供工厂bean的实例方法获取对象
<bean id="factory" class="com.zhiyou100.test02.TeacherFactoryInstance" />
<bean id="tea2" class="com.zhiyou100.test02.Teacher" factory-bean="factory" factory-method="getInstance" />
10 bean的生命周期
10.1 更改实体类:添加方法
package com.zhiyou100.test02;
import java.io.Serializable;
public class Teacher implements Serializable{
....
public void methodInit(){
System.out.println("初始化方法:::public void methodInit()");
}
public void methodDestroy(){
System.out.println("销毁方法:::public void methodDestroy()");
}
}
10.2 在核心配置文件中 通过属性init-method和destroy-method 指定初始化方法和销毁方法
<bean id="tea1" class="com.zhiyou100.test02.Teacher" init-method="methodInit" destroy-method="methodDestroy">
<property name="tid" value="1"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
11 bean的集合属性的赋值
11.1 创建实体类
public class Student implements Serializable{
private Integer sid;
private String sname;
private Float[] arr;
private List<Teacher> listTeas;
private Set<Integer> setInts;
private Map<Integer, String> mapProperty;
...
}
11.2 在配置文件中给属性赋值
<bean id="stu1" class="com.zhiyou100.test02.Student">
<property name="sid" value="1001"/>
<property name="sname" value="韩梅梅"/>
<property name="arr">
<array value-type="java.lang.Float">
<value>111.2</value>
<value>112.2</value>
<value>113.2</value>
<value>114.2</value>
</array>
</property>
<property name="listTeas">
<list value-type="com.zhiyou100.test02.Teacher">
<ref bean="tea11"/>
<ref bean="tea12"/>
<ref bean="tea13"/>
<ref bean="tea12"/>
<ref bean="tea11"/>
</list>
</property>
<property name="setInts">
<set value-type="java.lang.Integer">
<value>121</value>
<value>122</value>
<value>123</value>
<value>121</value>
</set>
</property>
<property name="mapProperty">
<map key-type="java.lang.Integer" value-type="java.lang.String">
<entry key="111" value="v_111"/>
<entry key="112" value="v_112"/>
<entry key="113" value="v_113"/>
<entry key="114" value="v_114"/>
</map>
</property>
</bean>
<bean id="tea11" class="com.zhiyou100.test02.Teacher">
<property name="tid" value="11"/>
<property name="tname" value="高老师1"/>
<property name="tsex" value="女"/>
</bean>
<bean id="tea12" class="com.zhiyou100.test02.Teacher">
<property name="tid" value="12"/>
<property name="tname" value="高老师2"/>
<property name="tsex" value="女"/>
</bean>
<bean id="tea13" class="com.zhiyou100.test02.Teacher">
<property name="tid" value="13"/>
<property name="tname" value="高老师3"/>
<property name="tsex" value="女"/>
</bean>
12 bean的自动装配
12.1 修改Student
public class Student implements Serializable{
private Integer sid;
private String sname;
private Teacher tea;
...
}
12.2 自动装配和手动装配
<bean id="stu1" class="com.zhiyou100.test02.Student">
<property name="sid" value="1001"/>
<property name="sname" value="韩梅梅"/>
</bean>
<bean id="stu2" class="com.zhiyou100.test02.Student">
<property name="sid" value="1002"/>
<property name="sname" value="韩梅梅"/>
<property name="tea" ref="t1"></property>
</bean>
<bean id="stu3" class="com.zhiyou100.test02.Student" autowire="byName">
<property name="sid" value="1003"/>
<property name="sname" value="韩梅梅"/>
</bean>
<bean id="t1" class="com.zhiyou100.test02.Teacher">
<property name="tid" value="121"/>
<property name="tname" value="高老师21"/>
<property name="tsex" value="女"/>
</bean>
<bean id="t2" class="com.zhiyou100.test02.Teacher">
<property name="tid" value="122"/>
<property name="tname" value="高老师22"/>
<property name="tsex" value="女"/>
</bean>
13 注解形式的ioc
13.1 导入jar::和配置的jar完全相同
13.2 在核心配置文件中通过context标签指定bean所在的包
<context:component-scan base-package="com.zhiyou100.test03"/>
13.3 创建实体类
package com.zhiyou100.test03;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
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.Repository;
@Component("tea1")
@Scope("singleton")
@Lazy
public class Teacher implements Serializable{
@Value("1001")
private Integer tid;
@Value("韩梅梅")
private String tname;
private String tsex;
@Resource
private School school;
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
{
System.out.println("构造代码块::"+this.hashCode());
}
public Integer getTid() {
return tid;
}
public void setTid(Integer tid) {
this.tid = tid;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public String getTsex() {
return tsex;
}
@Value("女")
public void setTsex(String tsex) {
this.tsex = tsex;
}
@Override
public String toString() {
return "Teacher [tid=" + tid + ", tname=" + tname + ", tsex=" + tsex + ", school=" + school + "]";
}
public Teacher(Integer tid, String tname, String tsex) {
super();
this.tid = tid;
this.tname = tname;
this.tsex = tsex;
}
public Teacher() {
super();
}
@PostConstruct
public void methodInit(){
System.out.println("初始化方法:::public void methodInit()");
}
@PreDestroy
public void methodDestroy(){
System.out.println("销毁方法:::public void methodDestroy()");
}
}
14 模拟springioc
14.1 创建java项目
14.2 创建实体类
public class Student implements Serializable{
{
System.out.println("构造代码块");
}
private Integer sid;
private String sname;
private Integer sage;
private Boolean sdy;
private Float score;
private Teacher teacher;
...
}
public class Teacher implements Serializable{
private Integer tid;
private String tname;
private String tsex;
...
}
14.3 创建核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="stu1" class="com.zhiyou100.test01.Student">
<property name="sid" value="1001"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="19"/>
<property name="sdy" value="true"/>
<property name="score" value="11.6"/>
</bean>
<bean id="stu2" class="com.zhiyou100.test01.Student">
<constructor-arg name="sid" value="1002"/>
<constructor-arg name="sname" value="韩寒"/>
<constructor-arg name="sage" value="19"/>
<constructor-arg name="sdy" value="false"/>
<constructor-arg name="score" value="33.5"/>
</bean>
<bean id="stu3" class="com.zhiyou100.test01.Student">
<property name="sid" value="1001"/>
<property name="sname" value="韩梅梅"/>
<property name="sage" value="19"/>
<property name="sdy" value="true"/>
<property name="score" value="11.6"/>
<property name="teacher" ref="tea1"/>
</bean>
<bean id="tea1" class="com.zhiyou100.test01.Teacher" >
<property name="tid" value="1002"/>
<property name="tname" value="高老师"/>
<property name="tsex" value="女"/>
</bean>
</beans>
14.4 创建类模拟ClassPathXmlApplicationContext
方法:1 构造方法::加载核心配置文件
方法:2 getBean方法:根据bean的id获取对象
方法:3 close方法:释放资源销毁对象
package com.zhiyou100.test01;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class MyClassPathXmlApplicationContext {
private Map<String, Object> mapBeans=new HashMap<String, Object>();
private InputStream in;
private Document doc;
public MyClassPathXmlApplicationContext(String fileName){
try {
in=new FileInputStream(new File("src/"+fileName));
doc=Utils.xml2Doc(in);
init();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void init()throws Exception{
NodeList beans=doc.getElementsByTagName("bean");
for (int i = 0; i < beans.getLength(); i++) {
Element beanEle=(Element)beans.item(i);
String id=beanEle.getAttribute("id");
String className=beanEle.getAttribute("class");
Class cla=Class.forName(className);
Object obj=null;
NodeList conZiList=beanEle.getElementsByTagName("constructor-arg");
if(conZiList==null||conZiList.getLength()==0){
obj=cla.newInstance();
NodeList proZiList=beanEle.getElementsByTagName("property");
for (int j = 0; j < proZiList.getLength(); j++) {
Element proEle=(Element)proZiList.item(j);
String name=proEle.getAttribute("name");
String value=proEle.getAttribute("value");
Field field=cla.getDeclaredField(name);
field.setAccessible(true);
if(value!=null&&!value.isEmpty()){
field.set(obj, Utils.changeType(value, field.getType()));
}else{
String ref=proEle.getAttribute("ref");
field.set(obj, mapBeans.get(ref));
}
}
}else{
Class[] argsTypes=new Class[conZiList.getLength()];
Field[] fieldArr=new Field[conZiList.getLength()];
String[] valueStrArr=new String[conZiList.getLength()];
Object[] valueObjArr=new Object[conZiList.getLength()];
for (int j = 0; j <conZiList.getLength(); j++) {
Element conZi=(Element)conZiList.item(j);
fieldArr[j]=cla.getDeclaredField(conZi.getAttribute("name"));
valueStrArr[j]=conZi.getAttribute("value");
valueObjArr[j]=Utils.changeType(valueStrArr[j], fieldArr[j].getType());
argsTypes[j]=fieldArr[j].getType();
}
Constructor constructor=cla.getDeclaredConstructor(argsTypes);
constructor.setAccessible(true);
obj=constructor.newInstance(valueObjArr);
}
mapBeans.put(id, obj);
}
}
public void close(){
try {
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object getBean(String name){return mapBeans.get(name);}
}
14.5 测试
MyClassPathXmlApplicationContext context=
new MyClassPathXmlApplicationContext("com/zhiyou100/test01/spring_config.xml");
Student s11=(Student)context.getBean("stu3");
System.out.println(s11);
context.close();