1.Spring简介
[1]为什么学习Sping框架
目前遇到的问题
- A、我们现在使用的MVC模式,发现层和层之间的耦合度太高了
- B、目前书写代码的后期扩展性不高
[2]解决方案
使用Spring: Spring是解决业务层和其他各层之间的耦合问题
[3]Spring简介
Spring: Spring framework
创始人:Rod Johnson
轮子理论:不新建轮子,使用旧轮子
[4]学习框架必备三要素
jar包 http://spring.io/projects
api https://docs.spring.io/spring/docs/current/spring-framework-reference/
源码 https://github.com/spring-projects/spring-framework/tags
[5]Spring学习的核心技能点
A、IOC:控制反转-----帮助我们创建对象的
B、AOP:面向切面----提升代码的拓展性
C、TX:声明式事务----事务管理
2.Spring中的IOC
[1]责任链
我们使用MVC进行开发的时候,数据在各层之间进行传递,数据在业务上构成一个链条,该链条称之为责任链
[2]基于责任链开发的缺点
基于责任链开发模式,我们发现代码层和层之间相互调用,造成代码层和层之间的耦合性过高。而我们写代码的时候讲究的原则是:高内聚,低耦合
[3]解决方案
Spring IOC:控制反转
[4]Spring IOC:控制反转
控制:就是指Spring创建对象的过程
反转:创建对象这个过程本来是由程序员做的,现在反交给Spring IOC进行创建
[5]代码实现
A、导包
B、创建类
public class Student {
public Student(){ //对象一旦被创建,该构造方法就会被调用
System.out.println("----对象已创建----");
}
public void eat(){
System.out.println("---eat()方法---");
}
}
C、书写配置文件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">
<!--相当于代替了 Student student = new Student()-->
<bean id="student" class="cn.qt.spring1.Student"></bean>
</beans>
D、解析XML调用对象
package cn.qt.spring1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//Student student = new Student();
//[1]解析XML文档
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// Student student = (Student) app.getBean("student");该方法未指定对象的类,默认为OBject类,需要强转成其对应的类
Student student1 = app.getBean("student", Student.class);//该方法指定了对象的类,对象的类即为getBean()方法的第二个参数
student1.eat();
}
}
E、运行结果
即完成了通过Spring IOC创建对象并调用对象的方法
Spring IOC的好处:实现了各层之间的解耦
3.Spring中IOC创建对象的方式
A、使用无参构造
B、使用有参构造
C、使用工厂方法模式
[1]使用无参构造
<bean id="student" class="cn.qt.spring1.Student"></bean>
[2]使用有参构造
<!--
Student stu2 = new Student("张三","男",18);
注意:<constructor-arg>标签中
[1]name的值和构造器的形参是保持一致的,而非实体类的属性。
[2]形参的顺序不用和标签中的顺序保持一致
[3]使用name属性调用,但是除了name属性,
还有index(从0开始),type:数据类型
建议三者都写上,即可确定唯一的构造方法
-->
<bean id="stu2" class="cn.qt.spring2.Student">
<constructor-arg name="age" value="18" index="2" type="int"></constructor-arg>
<constructor-arg name="name" value="张三" index="0" type="java.lang.String"></constructor-arg>
<constructor-arg name="sex" value="男" index="1" type="java.lang.String"></constructor-arg>
</bean>
[3]使用工厂方法模式
设计模式:是为了解决某一类问题的产生
用简单工厂模式创建对象
1.People接口
public interface People {
public void eat();
public void run();
}
2.Teacher类
public class Teacher implements People{
public Teacher(){
System.out.println("老师对象已被创建");
}
@Override
public void eat() {
System.out.println("老师吃的方法");
}
@Override
public void run() {
System.out.println("老师跑的方法");
}
}
3.Student类
public class Student implements People {
public Student(){
System.out.println("学生对象已被创建");
}
@Override
public void eat() {
System.out.println("学生吃的方法");
}
@Override
public void run() {
System.out.println("学生跑的方法");
}
}
4.Factory方法
public class Factory {
public People getInterface(String param){
if ("student".equals(param)){
return new Student();
}else if ("teacher".equals(param)){
return new Teacher();
}else {
return null;
}
}
//getInterface2除了是静态方法外与getInterface无任何区别
public static People getInterface2(String param){
if ("student".equals(param)){
return new Student();
}else if ("teacher".equals(param)){
return new Teacher();
}else {
return null;
}
}
}
5.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">
<!-- [3]用简单工厂模式创建对象 -->
<!-- Factory factory=new Factory() 非静态方法 -->
<bean id="factory" class="cn.qt.spring3.Factory"></bean>
<!-- 相当于People teacher=factory.getInterface(teacher) -->
<bean id="getInterface" factory-bean="factory" factory-method="getInterface">
<constructor-arg name="param" value="teacher"></constructor-arg>
</bean>
<!-- 相当于Factory.getInterface2("student"); 静态方法 -->
<bean id="factory2" class="cn.qt.spring3.Factory" factory-method="getInterface2">
<constructor-arg name="param" value="student"></constructor-arg>
</bean>
</beans>
4.Spring中的DI(依赖注入)
[1]DI(依赖注入)的概念
依赖:一个类在另一个类中作为全局属性时
注入:通过外部给自己属性(或其他内容)进行赋值
作用:给创建好的对象中的全局的属性或者对象进行赋值的操作
[2]DI的3种注入方式
两个实体类Class和Student
1.Clazz中包括以下属性和set()、get()方法、有参构造无参构造等
private String clazzno;
private String cname;
2.Student中包括括以下属性和set()、get()方法、有参构造无参构造等
private String stuno;
private String stuName;
private int age;
private String sex;
private Clazz clazz;
A、使用有参构造进行DI注入
<!--[1]使用有参构造进行DI注入-->
<bean id="cla" class="cn.qt.spring4.Clazz">
<constructor-arg name="clazzno" value="501"></constructor-arg>
<constructor-arg name="cname" value="java1班"></constructor-arg>
</bean>
<bean id="stu" class="cn.qt.spring4.Student">
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="stuno" value="001"></constructor-arg>
<constructor-arg name="stuName" value="张三"></constructor-arg>
<constructor-arg name="sex" value="男"></constructor-arg>
<constructor-arg name="clazz" ref="cla"></constructor-arg>
</bean>
B、使用set()方法进行DI注入
<bean id="cla" class="cn.qt.spring4.Clazz">
<constructor-arg name="clazzno" value="501"></constructor-arg>
<constructor-arg name="cname" value="java1班"></constructor-arg>
</bean>
<!-- [2]使用set方法进行DI注入
name:对象的属性名
value和ref的使用场景:
value:如果注入的属性时基本的属性类型(包括String),则使用value
ref:如果注入的属性类型是对象时,使用ref
-->
<bean id="stu" class="cn.qt.spring4.Student">
<property name="stuno" value="002"></property>
<property name="stuName" value="李四"></property>
<property name="sex" value="女"></property>
<property name="age" value="18"></property>
<property name="clazz" ref="cla"></property>
</bean>
C、DI自动注入
<!-- [3]DI中的自动注入-->
<bean id="clazz" class="cn.qt.spring4.Clazz">
<constructor-arg name="clazzno" value="501"></constructor-arg>
<constructor-arg name="cname" value="java1班"></constructor-arg>
</bean>
<!-- autowire="byName/byType/constructor"
底层走的是set方法
byName:在当前xml中被注入的【bean的id名称】和需要注入实体的【属性名】一致,才进行匹配注入。否则则为null
byType:在当前的xml中被注入的【bean标签的类型】和需要注入实体中的【属性的类型】一致,才进行匹配注入。否则则为null
底层走的是构造器
constructor:这个时候首先会根据[有参构造器的形参名]名称进行查找,如果名称没有一致的,在根据类型[有参构造器的类型]进行查找
需要注意:*在指定的类中必须提供合适的(构造器中有且仅有该类型的对象)有参构造器才可以
-->
<bean id="stu" class="cn.qt.spring4.Student" autowire="constructor"></bean>
[3]其他类型的注入
A、基本类型(Sting)
B、对象类型
C、数组类型
D、List
E、Set
F、Map
实体类User中的属性为
private String [] attr;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
<!-- 特殊类型的注入-->
<bean id="user" class="cn.qt.spring4.User">
<property name="attr">
<array>
<value>A</value>
<value>B</value>
<value>C</value>
<value>D</value>
</array>
</property>
<property name="list">
<list>
<value>A</value>
<value>B</value>
<value>C</value>
</list>
</property>
<property name="set">
<set><!--set两种属性:无序性和唯一性,两个value为A的标签只会保存一个-->
<value>A</value>
<value>A</value>
<value>C</value>
<value>D</value>
</set>
</property>
<property name="map">
<map>
<entry>
<key><value>A</value></key>
<value>1</value>
</entry>
</map>
</property>
</bean>
5.Scope作用域详解
- < bean>标签的一个属性,控制如何实例化对象。在默认情况下,Spring中的每个对象都是单例的(有效范围:同一个< bean>标签),即一个标签中获取的对象总是同一个。
- Scope属性可取值
2.1singleton:默认值,单例的。使用ApplicationContext.xml启动时实例化。
2.2 protopyte:原型,每次使用getbean方法时都实例化一个对象。
2.3 request:每次请求时实例化一个对象。
2.4 session:每次产生session(HttpSession)时实例化。
2.5 application:产生application对象时实例化,一般都实例化一次。
2.6 golbal session:全局Golbal Session,web应用中一个新的HttpSession对象,由spring-webmvc-portlet提供