Spring核心容器的详细解析以及IOC和DI和过程全解

1.spring的简介

spring是一个一站式的解决框架,旨在解决企业开发中各个层级之间的问题.
所谓一站式的解决方案:就是spring可以支持我们各个层级包括数据展示层,业务层和持久层都有对应的解决方案.
Spring的出现是为了取代 EJB(Enterprise JavaBean)开发模式的臃肿,低效,脱离现实

2.spring优点

方便解耦,简化开发
AOP编程的支持
申明式事务的支持
方便程序的测试等等

3.spring的架构体系


其他地方扒的,这次只聊Core Container(核心容器)

4.Core Container(核心容器)

容器用来装javaBean.
spring容器通过单例设计模式+工厂设计模式+反射的机制来加载获取类对象
java中单例设计模式定义:"一个类有且仅有一个实例,并且自行实例化向整个系统提供"
spring 核心容器core, context,beans, SpEL
context容器:提供了ApplicationContext容器,加载配置文件(获取唯一Id标识)  context.getBeans获取bean对象,加载完成对象
ApplicationContext.xml中配置Bean
	<bean id="userInterfaceImpl" class="com.youlin.spring.demo1.UserInterfaceImpl">
		<property name="username" value="张三"></property>
	</bean>
测试类中进行获取
	@Test
	public void getUser() throws Exception {
		//获取容器
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserInterface bean = (UserInterface) context.getBean("userInterfaceImpl");
		bean.sayHello();
	}
spring为某个属性赋值
bean内进行配置属性property  name  value  底层调用的是set get方法
普通的为对象赋值有两种get set  和构造器
spring也是两种方法
ApplicationContext是一个接口  它的最大接口是BeanFactory
Struts2  采用的对象是多例的.

5.spring的第一大特性IOC

Inversion Of Controller  控制反转
把创建对象的权利反转交给了spring,这一过程就叫做控制反转
在spring中加载对象,就是通过反射加载
讲个笑话:
什么是IOC? 就是通过反射加载对象的过程
什么是反射?  mysql的驱动连接就是通过反射来加载的.

1.容器创建的三种方式

第一种方式使用了ClassPathXmlApplicationContext子类对象
	/**
	 * 容器创建的第一种方式,也是最常用的一种方式
	 * 使用配置文件的相对路径
	 * spring 入门案例
	 * @throws Exception
	 */
	@Test
	public void getUser() throws Exception {
		//获取容器
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserInterface bean = (UserInterface) context.getBean("userInterfaceImpl");
		bean.sayHello();
	}
容器创建的第二种方式
使用了FileSystemXmlApplicationContext子类对象
	/**
	 * 容器创建的第二种方式
	 * 使用配置文件的路径是绝对路径
	 */
	@Test
	public void getFileSystemContainer() throws Exception {
		ApplicationContext context = new FileSystemXmlApplicationContext("D:\\workspace01\\springDay01\\src\\main\\resources\\ApplicationContext.xml");
		UserInterface bean = (UserInterface) context.getBean("userInterfaceImpl");
		bean.sayHello();
	}
第三种方式:
	/**
	 * 容器创建的第三种方式,已经过时了,不在使用
	 * 它是一种懒加载形式
	 * bean已经定义了,不用到的时候是不加载的,使用的时候才会加载
	 * 上面两种只管创建,不管你用不用
	 * @throws Exception
	 */
	@Test
	public void getXmlContainer() throws Exception {
		Resource resource = new ClassPathResource("ApplicationContext.xml");
		XmlBeanFactory beanFactory = new XmlBeanFactory(resource );
		UserInterface bean = (UserInterface) beanFactory.getBean("userInterfaceImpl");
		bean.sayHello();
	}

2.加载对象的三种方式

第一种方式:
默认构造器
上述例子
第二种方式:使用静态工厂来创建对象
创建静态工厂类
package com.youlin.spring.demo2;

public class UserBean2Factory {
	public static UserBean2 getUserBean2() {
		return new UserBean2();
	}
}
配置
<!-- 通过静态工厂来创建对象 -->
<bean id="userBean2Factory" class="com.youlin.spring.demo2.UserBean2Factory" factory-method="getUserBean2"></bean>
获取
	/**
	 * 第二种创建对象的方式:通过静态工厂来创建对象
	 */
	@Test
	public void getUserBean2() throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserBean2 bean = (UserBean2) context.getBean("userBean2Factory");
		bean.userBean2SayHello();
	}
第三种方式
通过实例工厂来创建对象,比较复杂,主要目的是可以在实例工厂初始化对象之前加塞一些自己的其他逻辑操作.
创建实例工厂
package com.youlin.spring.demo2;

public class UserBean3Factory {
	
	public UserBean3 getUserBean3() {
		return new UserBean3();
	}

}
配置
	<!-- 通过实例工厂来创建对象 -->
	<bean id="userBean3Factory" class="com.youlin.spring.demo2.UserBean3Factory"></bean>
	<bean id="userBean3" class="com.youlin.spring.demo2.UserBean3" factory-bean="userBean3Factory" factory-method="getUserBean3"></bean>
	
获取
	/**
	 * 第三种创建对象的方式,通过实例工厂来创建对象
	 * 可以在创建对象之前,加塞一些自己其他的逻辑,在实例工厂内加塞
	 * @throws Exception
	 */
	@Test
	public void getUserBean3() throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserBean3 bean = (UserBean3) context.getBean("userBean3");
		bean.sayHello();
	}

3.bean的作用域及作用范围以及生命周期

bean的属性作用域scope:
	<!-- bean的作用域与作用范围 -->
	<bean id="orders" class="com.youlin.spring.demo3.Orders" scope="singleton" init-method="initMethod" destroy-method="destroyMethod"></bean>
	/**
	 * 作用域与作用范围
	 * @throws Exception
	 */
	@Test
	public void getOrders() throws Exception {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		Orders bean = (Orders) context.getBean("orders");
		Orders bean2 = (Orders) context.getBean("orders");
		System.out.println(bean.toString());
		System.out.println(bean2.toString());
		context.close();
	}
默认为单例模式.

prototype : 多例
request : 创建对象并且丢到request作用域中去,一般不使用
session : 创建对象并且放到session作用域中去,一般不使用
singleton: 单例
生命周期: 初始化和销毁
初始化:init-method=""
创建的时候调用
销毁的方法: destroy-method=""
在容器关闭的时候被调用
初始化和销毁的方法都是我们自定义的
注:
ApplicationContext是一个接口没有close()方法
在其实现类ClassPathXmlApplicationContext中才会有close()方法
容器的关闭在spring与web整合的时候会提到
容器一般是不会关闭的,频繁的打开和关闭容器也是一种开销.
总结IOC控制反转
将创建对象的权利交给spring来完成
spring通过反射来加载对象
首先配置bean容器,然后再加载bean容器,由bean容器加载对象初始化对象.

6.Spring的第二大特性 DI   Dependency Injection  依赖注入

把我们对对象属性赋值的过程交给spring
就是spring给对象属性赋值的一个过程
普通属性赋值两种,构造器,get,set两种
DI也是这两种
先有IOC,再有DI,即先有创建对象,再有属性赋值
赋值对象属性通过ref来进行引用日期Date也需要
bean没有配置id,也可以获取对象,通过.class反射的方法来获得对象
赋值方式
通过构造器来为属性赋值
	<!-- 通过构造器来为属性赋值 -->
	<bean id="jerry" class="com.youlin.spring.demo4.Jerry">
		<!-- 通过constructor-arg来为我们的属性赋值
			name 指定哪个属性的名称
		 -->
		<constructor-arg name="name" value="jerry"></constructor-arg>
		<constructor-arg name="sex" value="1"></constructor-arg>
		<constructor-arg name="color" value="brown"></constructor-arg>
	</bean>
通过索引赋值
	<!-- 通过索引来为属性赋值 -->
	<bean id="jerry" class="com.youlin.spring.demo4.Jerry">
		<constructor-arg index="0" value="jerry2"></constructor-arg>
		<constructor-arg index="1" value="0"></constructor-arg>
		<constructor-arg index="2" value="黑白色"></constructor-arg>
	</bean>
通过P名称空间和C名称空间赋值
p名称空间是property的简写
C名称空间是constructor-arg简写
zhuyaoshi简化属性赋值的操作
	<!-- 通过P名称空间来为属性赋值 -->
	<bean id="tom" class="com.youlin.spring.demo4.Tom" p:age="10" p:tomName="tom" ></bean>
	
	<!-- 通过C名称空间来为构造器的属性注入 -->
	<bean id="jerry4" class="com.youlin.spring.demo4.Jerry" c:color="白色" c:sex="0" c:name="jerry4" ></bean>
	
SpEL表达式
类似于jstl与el表达式可以支持我们在为属性赋值的时候,通过spel表达式来进行更改我们的属性
#{ }
	<!-- spel表达式 -->
	<bean id="user2" class="com.youlin.spring.demo4.User">
		<property name="age" value="10"></property>
		<property name="username" value="tom"></property>
	</bean>
	<bean id="tom2" class="com.youlin.spring.demo4.Tom">
		<property name="tomAge" value="#{user2.getAge()+20}"></property>
		<property name="tomName" value="#{user2.getUsername()+'tomtom'}"></property>
		<property name="jerry" value="#{jerry4}"></property>
	</bean>

未完待续......
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章