Spring学习笔记
Spring是一个非常活跃的开源框架;它是一个基于Core来构架多层JavaEE系统的框架,它的主要目地是简化企业开发(Spring架构图)。
Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”。使用框架一般要学习使用框架的api,但是Spring不需要(学习框架就是学习它的api)。
Spring的核心是IOC(反转控制)与AOP(面向切面编程)。
Spring学习核心问题:
1)Spring容器是干么用的
2)如何帮助我们创建对象的?
3)创建对象的三种方式?
4)创建对象的两种时机?
5)哪种创建对象的时机比较好?
6)Spring如何管理对象的作用域和生命周期?
Spring配置文件:applicationContext.xml
SpringIOC(控制反转):把对象的创建、初始化、销毁等工作交给spring容器来做。由spring容器控制对象的生命周期(换句话说就是,让spring容器帮助我们创建对象,这样程序员就能专注于业务逻辑的实现)。
如何将一个类放到Spring容器里面,让它帮助我们创建对象呢?
在配置文件applicationContext.xml中对类进行配置。将类放到Spring容器里面,这个类就是bean,id是类的唯一标识,class表示全类名。把类名给Spring容器,让它帮助我们创建对象。
Spring帮助我们创建对象的步骤:
1)启动Spring容器。2)把对象从Spring容器中取出来。3)调用对象中的方法。
都是有模板性代码的,不需要关心对象是怎么创建的,关注于业务逻辑的处理就可以了。
Spring创建对象的三种方式?
1)调用默认的构造函数进行创建对象:如果写了有参数的构造函数,因为找不到无参数的函数,就会报错。
2)利用静态工厂的方式创建对象:Spring调用工厂方法创建对象,但是真正创建对象还是程序员来完成的。
3)实例工厂方法。
在Spring的配置文件中,只要是bean节点,Spring就会为该bean创建对象。
Spring创建对象的时机?在单例模式下(Scope)
1)默认情况下,启动Spring容器时创建对象。
2)在调用getBean()方法的时候创建对象。
在spring的配置文件bean中有一个属性lazy-init="default/true/false"
a、如果lazy-init为"default/false"在启动spring容器时创建对象。
b、如果lazy-init为"true",在context.getBean时才要创建对象。
在多例的情况下,调用getBean()方法时,创建对象。
哪种创建对象的时机比较好?
第一种情况下,可以在启动spring容器的时候,检查spring容器配置文件的正确性,如果再结合tomcat, 如果spring容器不能正常启动,整个tomcat就不能正常启动。但是这样的缺点是把一些bean过早的放在了内存中,如果有数据,则对内存来是一个消耗(对象的生命周期变长了)。
第二种情况下,可以减少内存的消耗,但是不容易发现错误。
spring的bean中的scope
1、由spring产生的bean默认是单例的(可以实现数据共享)
2、可以在spring的配置文件中,scope的值进行修改="singleton/prototype"
3、如果spring的配置文件的scope为"prototype",则在得到该getBean()时才创建对象。
spring容器对对象生命周期的管理:
1、Spring容器创建对象
2、执行init方法
3、调用自己类的方法
4、当Spring容器关闭的时候执行destroy方法(此时对象销毁),如何关闭Spring容器呢。
Spring DI:依赖注入:给对象的属性赋值。
1、利用set方法给属性赋值;property用来描述一个类的属性,并且对类的属性进行赋值,在bean节点下面。
1)、基本类型的的封装类,String等类型通过value进行赋值。
2)、引用类型通过ref进行赋值。
注意:一个类中的属性都可以采用SpringID的方式进行赋值,但是一般不常用,这种方式主要用于特定场合。
Spring容器会解析bean节点下的所有property对象,解析name和value,然后通过调用set方法进行赋值。
2、利用构造函数给属性赋值
SpringID的说明:如果Spring配置文件中的bean中没有<constructor-arg>元素,则调用默认的构造函数;如果Spring的配置文件中有<constructor-arg>元素,则该元素是唯一确定的构造函数。
index代表参数的位置,从0开始计算。
type表示参数的类型 java.lang.String。
value 给基本类型赋值。
ref给引用类型赋值。
SpringIOC和DI的意义:实现了完全的面向接口编程。
利用springIOC和DI实现MVC的模拟例子:
把接口放到Spring容器中(配置文件中没有意义的)
SpringInit类的作用
Spring注解:说明(可以少写一些代码)
1)在java中注解就是为了说明某一部分的作用。
2)注解都可以用于哪里是@Target注解起的作用。
3)注解可以标注在ElementType枚举类所指定的位置。
4)用来解析注解的类成为注解解析器。
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="main.com.tniu"/>
<!--引用另一个配置文件-->
<import resource="applicationContext_create.xml"/>
<!--在Spring容器中注册,lazy-init用于标记在在什么时候创建对象-->
<bean id="Student" class="main.com.tniu.Student" lazy-init="default"/>
<!--lazy-init懒加载,在调用getBean方法的时候创建对象-->
<bean id="Teacher" class="main.com.tniu.Teacher" lazy-init="true"/>
<!--通过静态工厂创建对象,factory-method表示调用那个工厂方法帮组我们创建对象-->
<bean id="ObjectFactory" class="main.com.tniu.ObjectFactory" factory-method="getInstance"/>
<!---->
<!--配置Scope,默认是单例模式singleton,prototype表示多例的-->
<bean id="SingleEntity" class="main.com.tniu.SingleEntity" scope="prototype"/>
<!--对象的初始化和销毁:init-method,destroy-method-->
<bean id="InitAndDestroy" class="main.com.tniu.InitAndDestroy" init-method="init" destroy-method="destory"/>
<!--通过set方法给属性赋值-->
<bean id="TestSetMethod" class="main.com.tniu.TestSetMethod">
<property name="id" value="1"/>
<property name="name" value="陈如水"/>
<property name="student" ref="Student"/>
<!--通过对list集合进行赋值-->
<property name="lists">
<list>
<value>list1</value>
<ref bean="Student"/>
<value>list2</value>
</list>
</property>
<!--对property集合进行赋值-->
<property name="prop">
<props>
<!--只能是字符串类型-->
<prop key="k1">
test
</prop>
<prop key="k2">
test2
</prop>
</props>
</property>
<!--对set集合进行赋值-->
<property name="sets">
<set>
<value>test</value>
<ref bean="Student"/>
<value>set1</value>
</set>
</property>
<!--对map集合进行赋值-->
<property name="map">
<map>
<entry key="key1">
<value>v1</value>
</entry>
<entry key="key2">
<value>v2</value>
</entry>
</map>
</property>
</bean>
<bean id="ConstructorEntity" class="main.com.tniu.ConstructorEntity">
<!--一定要和构造函数中参数的位置对应,在这里犯过错-->
<constructor-arg index="0" type="java.lang.String" value="陈如水"/>
<constructor-arg index="1" type="main.com.tniu.Student" ref="Student"/>
<constructor-arg index="2" type="java.lang.Long" value="11"/>
</bean>
</beans>
package main.com.tniu;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by Administrator on 2017/7/11.
*/
public class Test {
/**
* Spring帮助我们创建对象的过程
* ApplicationContext
* ClassPathXmlApplicationContext
*/
@org.junit.Test
public void testSpring() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("Student");
student.sayHello();
}
/**
* 主配置文件引用另一个配置文件
*/
@org.junit.Test
public void testImport() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("Person");
person.sayPerson();
}
/**
* 通过别名获取对象
*/
@org.junit.Test
public void testAlias() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("alias");
person.sayPerson();
}
/**
* 容器启动的时候创建对象
*/
@org.junit.Test
public void testCreateObject() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("容器启动的时候创建对象");
Student student = (Student) context.getBean("Student");
student.sayHello();
//打印顺序:通过构造方法创建对象--->容器启动的时候创建对象
}
/**
* 调用getBean()的时候创建对象
*/
@org.junit.Test
public void testCreateObjectTwo() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("getBean创建对象");
Teacher teacher = (Teacher) context.getBean("Teacher");
teacher.sayHello();
}
/**
* 创建对象的方式,Spring容器通过调用构造方法获取对象
* 通过静态工厂创建对象
* 需要把静态工厂类加入到配置文件当中
*/
@org.junit.Test
public void createMethod() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//直接转化成Student类
Student student = (Student) context.getBean("ObjectFactory");
student.sayHello();
}
/**
* Spring帮助我们创建的对象是不是单例的?
* 如果是单例的,就存在数据共享(对象中的成员变量和成员方法)
* 两个对象的内存地址值是一样的,说明是单例的;
* 如何去验证数据共享呢
* 如果修改bena中的Scope属性为prototype,则变成多例的,地址值是不一样的
* 注意:如果设置Scope属性为prototype,则对象是在调用getBean()方法的时候创建,在使用Struct2的时候
* action的创建必须是多例的,并且需要在容器启动的时候创建,所以要用到scope属性。
*/
@org.junit.Test
public void testSingle() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("Student");
System.out.println(student);
student.getList().add("a");
Student student1 = (Student) context.getBean("Student");
student1.getList().add("b");
System.out.println(student1);
//打印集合的长度,结果为2
System.out.println(student1.getList().size());
}
/**
* 初始化方法和销毁方法的调用
* 对象的生命周期
* 如何关闭Spring容器 close()方法
*/
@org.junit.Test
public void testInitAndDestroy() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
InitAndDestroy initAndDestroy = (InitAndDestroy) context.getBean("InitAndDestroy");
//打印结果:构造方法--->init方法
ClassPathXmlApplicationContext app = (ClassPathXmlApplicationContext) context;
app.close();
}
/**
* 通过set方法给类的属性赋值
* 没有能打印出结果
*/
@org.junit.Test
public void testSetMethod() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TestSetMethod testSetMethod = (TestSetMethod) context.getBean("TestSetMethod");
testSetMethod.toString();
}
/**
* 通过构造函数进行赋值
* 可以进行正常的打印
*/
@org.junit.Test
public void testSetMethodCon() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ConstructorEntity con = (ConstructorEntity) context.getBean("ConstructorEntity");
System.out.println(con.getName());
System.out.println(con.getStudent());
System.out.println(con.getId());
}
}