如果转载文章请注明出处, 谢谢 !
本系列文章是学习完 Spring4.3.8 后的详细整理, 如果有错误请向我指明, 我会及时更正~😝
Spring4.3.8
Spring意思是春天, 于2003 年兴起的一个轻量级的Java开源框架,由Rod Johnson(音乐博士) 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。
框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
它以IoC(控制反转)和AOP(面向切面编程)两种先进的技术为基础,完美的简化了企业级开发的复杂度。
1. Spring 架构图
2. 开发 Spring 所需要的工具
2.1 Spring 的 jar 包
- Spring 核心功能(CoreContainer): spring-core, spring-beans, spring-context, spring-expression, commons-logging
2.2 Spring 配置文件
默认情况下命名为 applicationContext.xml ,可以建立多个 xml 文件.
3. Spring 基本功能详解
3.1 SpringIoC
Spring的控制反转:把对象的创建、初始化、销毁等工作交给spring容器来做。 由spring容器控制对象的生命周期。
IoC : Inverse Of Control(控制反转)
- 把自己 new 的东西改为由容器提供
a) 初始化具体值
b) 装配 - 好处:灵活装配
3.2 Spring 容器内部对象
3.2.1创建对象的方式
3.2.1.1 无参构造函数
public class HelloWorld {
public HelloWorld(){
System.out.println("spring 在默认的情况下,使用默认的构造函数");
}
public void sayHello(){
System.out.println("hello");
}
}
<!--
一个bean就是描述一个类
id就是标示符
命名规范:类的第一个字母变成小写,其他的字母保持不变
class为类的全名
-->
<bean id="helloWorld" class="com.lanou.domain.HelloWorld"></bean>
@Test
public void testHelloWorld(){
//启动spring容器
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
//从spring容器中把对象提取出来
HelloWorld helloWorld=(HelloWorld)context.getBean("helloWorld");
helloWorld.sayHello();
}
3.2.1.2 有参构造函数
public class Person {
private String name;
private int age;
private String gender;
public Person(String name, int age, String gender) {
System.out.println("使用有参构造函数");
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
<bean id="person" class="com.lanou.domain.Person">
<!--根据参数名称注入-->
<constructor-arg name="name" value="大老王"/>
<!--根据索引index注入-->
<constructor-arg index="1" value="24"/>
<!--根据构造器参数的类型-->
<constructor-arg type="java.lang.String" value="men"/>
</bean>
public void iocPersonTest() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person");
System.out.println(person);
}
3.2.1.3 静态工厂
public class HelloWorldFactory {
public static HelloWorld getInstance(){
return new HelloWorld();
}
}
<!--静态工厂
静态方法,静态方法不需要实例化对象,
class指定的就是工厂类型
factory-method一定是工厂里面的静态方法
-->
<bean id="helloWorldFactory" class="com.lanou.domain.HelloWorldFactory" factory-method="getInstance"></bean>
/**
* 静态工厂
* 在spring 内部,调用了HelloWorldFactory 内部的 getInstance 内部方法
* 而该方法的内容,就是创建对象的过程,是由程序员来完成的
* 这就是静态工厂
* */
@Test
public void testHelloWorldFactory(){
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld=(HelloWorld)context.getBean("helloWorldFactory");
helloWorld.sayHello();
}
3.2.1.4 实例工厂
public class HelloWorldFactory2 {
public HelloWorld getInstance(){
return new HelloWorld();
}
}
<!--实例工厂
工厂类创建对象
工厂类,实例方法,必须先创建工厂
再创建user对象,用factory的实例方法
-->
<bean id="helloWorldFactory2" class="com.lanou.domain.HelloWorldFactory2">
</bean>
<!--factory-bean 指向实例工厂的bean-->
<!--factory-method 实例工厂对象的方法-->
<bean id="helloWorld3" factory-bean="helloWorldFactory2" factory-method="getInstance">
</bean>
/**
* 实例工厂
* 1.spring容器(beans)创建了一个实例工厂的bean
* 2.该bean 调用了工厂方法的getInstance 方法产生对象
* */
@Test
public void testHelloWorldFactory2(){
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
HelloWorld helloWorld=(HelloWorld)context.getBean("helloWorld3");
helloWorld.sayHello();
}
3.2.2对象的 scope
简单说就是对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式。
目前,scope的取值有5种取值:
在Spring 2.0之前,有singleton和prototype两种;
在Spring 2.0之后,为支持web应用的ApplicationContext,增强另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用。
3.2.2.1 singleton(默认)
每个Spring IoC 容器中一个bean定义只有一个对象实例(共享).
此取值时表明容器中创建时只存在一个实例,所有引用此bean都是单一实例。此外,singleton类型的bean定义从容器启动到第一次被请求而实例化开始,只要容器不销毁或退出,该类型的bean的单一实例就会一直存活,典型单例模式,如同servlet在web容器中的生命周期。
3.2.2.2 prototype
允许bean可以被多次实例化(使用一次就创建一个实例) . Spring不能对一个prototype bean的整个生命周期负责. 无论lazy-init 的值是什么, 都在 context.getBean时才创建对象.
spring容器在进行输出prototype的bean对象时,会每次都重新生成一个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。也就是说,容器每次返回请求方该对象的一个新的实例之后,就由这个对象“自生自灭”,最典型的体现就是spring与struts2进行整合时,要把action的scope改为prototype。
3.2.2.3 Request
再次说明 request,session和global session类型只实用于web程序,通常是和XmlWebApplicationContext共同使用,作用域仅在基于web的Spring ApplicationContext情形下有效。
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前 HTTP request 内有效。当处理请求结束,request作用域的bean实例将被销毁。
3.2.2.4 Session
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。
3.2.2.5 Global session
在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。
3.2.3 初始化 bean 的时机
Spring 默认在启动时将所有singleton bean提前进行实例化。提前实例化意味着作为初始化的一部分,ApplicationContext 会自动创建并配置所有的singleton bean.
通常情况下这是件好事。因为这样在配置中有任何错误能立即发现。
lazy-init="true" OR "false"
Lazy-init 为false,spring容器将在启动的时候报错(比较好的一种方式)
Lazy-init 为true, spring容器将在调用该类的时候出错。
<bean id="per1" class="com.lanou.domain.Person"/>
<bean id="per2" class="com.lanou.domain.Person" lazy-init="true"/>
可以打断点查看无参构造函数的执行
@Test
public void testPerson_lazy_init_true(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("per1");
/* lazy-init="true"
* 在 context.getBean("per2") 时才创建该对象
* */
Person person2 = (Person) context.getBean("per2");
}
如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init=“true“,如下:
<beans default-lazy-init="true“ ...>
3.2.4 init, destroy
Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。
public class Person {
public void init(){
System.out.println("初始化");
}
public void destroy(){
System.out.println("销毁");
}
}
<bean id="per1" class="com.lanou.domain.Person" init-method="init" destroy-method="destroy"/>
当 per1 被载入到Spring容器中时调用init-method方法。当 per1 从容器中删除时调用 destroy-method(scope = singleton有效)
/**
* 在构造方法之后立即执行 init 方法,
* 如果 spring 执行close方法, 在执行该方法前执行 destroy 方法
*/
@Test
public void testPerson_init_destroy() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("per1");
((ClassPathXmlApplicationContext) context).close(); //spring 容器关闭
}
3.3 别名
<bean id="car" name="BMCar" class="com.lanou.domain.Car"></bean>
<!-- name的属性值和id对应-->
<alias name="car" alias="QQ"/>
<alias name="car" alias="劳斯莱斯"/>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car1 = (Car) context.getBean("car");
Car car2 = (Car) context.getBean("QQ");
Car car3 = (Car) context.getBean("劳斯莱斯");
// 都是同一个对象
System.out.println(car1);
System.out.println(car2);
System.out.println(car3);
Spring4.3.8学习[二]
Spring4.3.8学习[三]
Spring4.3.8学习之 与 Struts2 整合[四]
Spring4.3.8学习之与Hibernate4 整合[五]
Spring4.3.8学习之S2SH 整合[六]