spring框架(二)——spring概述与spring的核心之IOC

上面一节我们说了spring的体系和jar包的依赖关系,这节笔者主要详解一下spring3.x 

一、Spring概述

1、Spring是什么?

Spring是分层的Java SE/EE应用 full-stack轻量级开源框架,以IoC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层Spring MVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE企业应用开源框架。

2、Spring3.X的体系结构

spring框架(二)——spring概述与spring的核心之IOC_第1张图片

4、Spring带来的好处

方便解耦,简化开发
通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
AOP编程的支持
通过Spring的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
方便集成各种优秀框架
Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。
降低JavaEE API的使用难度
Spring对JavaEE API(如JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API的使用难度大为降低。
Java源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是Java技术的最佳实践的范例。

5、Spring的资源

5.1 下载开发资源包

官方网站: http://spring.io/

5.2、Spring的资源包介绍


spring Framework的官方发行包内部结构为:spring框架(二)——spring概述与spring的核心之IOC_第2张图片

5.3、关于资源包的说明

Spring Framework官方最新版本是4.3.2。但是能下载到的就是3.2,这是Spring3这个版本的最后一个官方资源包。之后的版本全用MAVEN整合了。
Spring依赖的第三方资源包能下载的版本就是3.0.2。后面的也都整合到MAVEN里面去了。

6、搭建Spring核心开发环境

6.1、拷贝最基本的核心jar包

spring框架(二)——spring概述与spring的核心之IOC_第3张图片

根据第一节。添加这4个jar包以及它的依赖包(spring-Context其实还依赖了aop但是这里因为讲解IOC所以不用依赖也是可以的)。所以上图为他们的4个jar包名称。

6.2、核心依赖的jar包(日志输出)

commons-logging或log4j:用哪个都行。

spring框架(二)——spring概述与spring的核心之IOC_第4张图片

6.3、Spring的配置文件:基于xml或注解的方式

(下面搭建项目时在讲解)

概述部分讲解完毕。下面开始spring的核心之一IOC部分

二、Spring的核心之IoC(Inversion of Control 控制反转)

1、IoC是什么?

spring框架(二)——spring概述与spring的核心之IOC_第5张图片

注意:这里需要理解什么是注入。(举例,比如普通的set方法就是一种注入等等。)

2、Spring容器

Spring容器简单理解就是用于存放对象的一个boss那么一个东西。

3、Spring的IoC入门(注意:这里只是IOC的入门案例,了解ioc是怎么个过程)

3.1、建立一个java工程(没有整合web项目,所以jar工程就够用了)

3.2、导入Spring的核心jar包(5个jar包)

spring框架(二)——spring概述与spring的核心之IOC_第6张图片

3.3、建立一个XML配置文件

spring框架(二)——spring概述与spring的核心之IOC_第7张图片

注意:现在xml文件用什么名字无所谓。

3.4、资源交给Spring容器管理(当你写好了controller层,service层,以及dao层时需要交给spring来管理他们的关系)

比如:写好了dao层之后:

spring框架(二)——spring概述与spring的核心之IOC_第8张图片

3.5、Spring容器的初始化及资源的获取

配置依赖注入:service与dao层之间的关系:

spring框架(二)——spring概述与spring的核心之IOC_第9张图片

在service层中写一个register方法,调用dao层的方法(注入的dao中有save方法)如下:

package springIoc.service;

import springIoc.dao.XXDao1;

public class XXService1 {

	private XXDao1 xxDao1;

	public void setXxDao1(XXDao1 xxDao1) {
		this.xxDao1 = xxDao1;
	}
	public void rgeister(){
		xxDao1.save();
	}
	
}
初始化和资源的获取测试:

package springIoc.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import springIoc.service.XXService1;

public class Client {

	public static void main(String[] args) {
		/* 注意这是直接new对象获取,耦合度很高,没有调用spring来管理的bean == 不采用
		 * XXService1 xxService1 = new XXService1();
			xxService1.rgeister();
		*/
		//Spring容器的初始化
		
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/bean.xml");
		//获取资源
		//XXDao1 xxdao1 = (XXDao1) ac.getBean("xxDao1");
		//xxdao1.save();
		
		XXService1 xxService1 = (XXService1) ac.getBean("xxService1");
		xxService1.rgeister();
	}
}
结果成功!

4、Spring中API的体系结构(了解)

spring框架(二)——spring概述与spring的核心之IOC_第10张图片

4.1、核心接口和类

BeanFactory:它使用的是延迟加载思想。当我们需要用bean时,才去创建对象。
ApplicationContext:它继承自BeanFactory接口,还继承了很多其他接口。功能比BeanFactory强大。它用的不是延迟加载思想,而是在加载配置文件时就创建了。(推荐)
FileSystemXmlApplicationContext:配置文件在本地磁盘上,使用该类加载。
ClassPathXmlApplicationContext :配置文件在classpath中,使用此类加载。

特别注意:以上主要ioc已经讲解完毕!下面的Ioc配置部分很重要,两种方式在实际开发中用到的都很多!

5、基于XML的spring的IoC配置

5.1、Spring实例化bean的方式

a、调用默认的构造方法 (推荐)

 

b、静态工厂方法初始化:老系统才有可能用到(现在已经完全不用了)
c、实例工厂方法初始化:老系统才有可能用到(现在已经完全不用了)

5.2、Bean的作用范围(Bean下的scope标签)

* scope属性的取值:
* singleton			:默认值.单例的.Spring生成Bean的时候采用的是单例的模式.
* prototype			:多例的.Spring生成Bean的时候采用的是多例的模式.每次getBean的时候都会得到一个新的Bean的实例.(与Struts2整合时要使用此值)
* request			:应用在web应用中.创建一个Bean的实例将Bean实例存入到request域中.
* session			:应用在web应用中.创建一个Bean的实例将Bean的实例存入session域中.
* globalsession			:应用在web应用中.全局session.一般用于Porlet应用环境.如果没有Porlet环境.配置全局session等价于session.

5.3、Bean的生命周期方法

init-method:
Bean初始化的时候执行的方法.
destroy-method:
Bean销毁的时候执行的方法.必须是在scope=”singleton”情况下使用.

拓展:

Bean的完整的生命周期:

Spring框架管理Bean的时候,非常精确.Bean的生成过程中有11个步骤.11个步骤才构成了Bean的完整的生命周期.

1.instantiate bean对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware 执行 setBeanName
4.如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
6.如果Bean实现InitializingBean 执行 afterPropertiesSet 
7.调用 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现 DisposableBean 执行 destroy
11.调用 指定销毁方法 customerDestroy

* 第三步和第四部为了让Bean了解Spring的环境的..
* 第五步和第八部是实现了一个接口BeanPostProcessor.
注意:当非单例时,初始化方法正常执行,但是销毁方法就不会执行了。

5.4、依赖注入(DI)

a、构造器注入(调用默认构造方法):通过传参数

spring框架(二)——spring概述与spring的核心之IOC_第11张图片

0 先定义一个bean类,只提供有参的构造方法(并给每个参数提供get方法,方便测试时判断是否注入进去值)

package springIoc.bean;

import java.util.Date;

public class Bean1 {
	private String name;
	private int age;
	private Date birthday;
	
	//提供了有参构造方法,没有提供默认的构造方法
	public Bean1(String name, int age, Date birthday) {
		super();
		this.name = name;
		this.age = age;
		this.birthday = birthday;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public Date getBirthday() {
		return birthday;
	}
	
}
1、编写bean.xml交给spring管理这个类。
spring框架(二)——spring概述与spring的核心之IOC_第12张图片

2.编写测试类,判断是否注入成功

package springIoc.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import springIoc.bean.Bean1;
public class Client {

	public static void main(String[] args) {
		//Spring容器的初始化
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/bean.xml");
		//获取资源
		Bean1 bean1 = (Bean1) ac.getBean("bean1");
		System.out.println("姓名:"+bean1.getName()+"年龄:"+bean1.getAge()+"现在时间:"+bean1.getBirthday());
	}
}
打印出:姓名:小马同志年龄:26现在时间:Fri Oct 27 09:47:20 CST 2017 
b、属性注入:推荐(也是常用的)

0 先定义一个bean类,定义的字段需要提供setter方法(不然注入不进去)并提供默认的构造方法(必须)

package springIoc.bean;

import java.util.Date;

public class Bean1 {
	private String name;
	private int age;
	private Date birthday;
	public Bean1() {
		super();
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	
}
1、编写bean.xml交给spring管理这个类。

    			

	
	
	
	
2.编写测试类
package springIoc.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import springIoc.bean.Bean1;
public class Client {

	public static void main(String[] args) {
		//Spring容器的初始化
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/bean.xml");
		//获取资源
		Bean1 bean1 = (Bean1) ac.getBean("bean1");
		System.out.println("姓名:"+bean1.getName()+"年龄:"+bean1.getAge()+"现在时间:"+bean1.getBirthday());
	}
}
测试成功。
c、p名称空间(不做细讲)
d、SpEL(Spring Expression Lanaguage)

e、注入集合数据

5.5、团队开发:多个Spring配置文件

两种形式:
* 加载配置文件的时候一并引入.
* ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
				"applicationContext.xml", "applicationContext2.xml");

* 总的配置文件中引入其他的配置文件.
* 
基于xml的配置文件就讲解到这。需要会。下面说一下基于注解的配置也是同样重要,

6、基于注解的spring的IoC配置

6.1、注解的使用前提(3个步骤必须有的!)

a、引入context的名称空间

b、指定要扫描的包

c、在Bean上面加入@Component注解

0、配置a和b的步骤

spring框架(二)——spring概述与spring的核心之IOC_第13张图片

1 之后执行c在指定的类中添加注解(control层和service层以及dao层都需要添加各自的注解)(稍后会有详细的注解介绍)

package springIoc.dao;

import org.springframework.stereotype.Component;

/**
 * @Component是spring的一个注解,它是把XXDao1看做一个组件。
 * 就相当于xml中 
 * @author mch
 *
 */
@Component
public class XXDao1 {

	public void save() {
		System.out.println("SPRING3.XIOC成功了");
	}

}
注意:@Component(value="xxDao1") 也可以写成这种注解而value值相当于bean的id

2、编写测试类运行结果

package springIoc.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import springIoc.dao.XXDao1;
public class Client {

	public static void main(String[] args) {
		//Spring容器的初始化
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/springxml.xml");
		//获取资源
		XXDao1 xxDao1 = (XXDao1) ac.getBean("xxDao1");
		xxDao1.save();
	}
}

6.2、常用注解

a、@Component
作用:让Spring容器管理当前的Bean(实例化)
属性:
value:指定bean的名称。默认值是当前类简单名称(不是全类名)首字母小写。

b、@Component的衍生注解@Controller @Service @Repository
作用:和@Component作用一样,让Spring容器管理(实例化)当前的bean。
属性: value:指定bean的名称。默认值是当前类的简单类名首字母小写
特点:在三成架构中,每个注解对应一层,使语义更加明确。
@Controller:一般用在表现层,比如struts2的action上
@Service:一般用在业务层,比如Service实现
@Repository:一般用在持久层,比如Dao实现

c、@Autowired
作用:自动按类型注入需要的对象。当使用了该注解时,setter就不是必须的了。
属性:
required:是否必须注入成功。默认值是true。
true:必须注入成功,如果出现注入失败,抛出异常。
false:不一定注入成功,不抛异常。
注意事项:
一个Service接口:IBookService
两个Service实现:BookServiceImpl1 BookServiceImpl2
由于@Autowired是自动按类型注入,当使用接口类型时,就看变量的名称,如果变量名称是bookServiceImpl1,则使用BookServiceImp1这个实现类,
如果变量名是bookServiceImpl2,则使用BookServiceImpl2这个实现类。如果没有符合规范的名称(类名首字母小写),则报错。
到底注入哪个实现类:
@Autowried
private BookService bookServiceImpl1;//注入BookServiceImpl1
@Autowried
private BookService bookServiceImpl2;//注入BookServiceImpl2
@Autowried
private BookService bookService;//注入失败

d、@Value
作用:注入基本类型和String。
属性:value:SpEL表达式,要注入的值

package springIoc.dao;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @Component是spring的一个注解,它是把XXDao1看做一个组件。
 * 就相当于xml中 
 * @author mch
 *
 */
@Component(value="xxDao1")
public class XXDao1 {

	@Value("小码")
	private String name;
	
	public void save() {
		System.out.println("SPRING3.XIOC成功了");
	}

	public String getName() {
		return name;
	}
	
}
提供get方法查看是否注入成功
package springIoc.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import springIoc.dao.XXDao1;
public class Client {

	public static void main(String[] args) {
		//Spring容器的初始化
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("springIoc/springxml.xml");
		//获取资源
		XXDao1 xxDao1 = (XXDao1) ac.getBean("xxDao1");
		xxDao1.save();
		System.out.println(xxDao1.getName());
	}
}
结果为成功
e、@Qualifier
作用:要配合@Autowried来一起使用,通过它指定要注入的bean的名称。按类型注入失效了。
属性:value:要注入的bean的名称

f、@Resource
作用:如同@Autowire和@Qualifier,是规范JSR-250中定义的(JCP)。通过指定bean的名称注入对象。
属性: name:要注入的bean的名称

g、@PostConstruct(了解)
作用:用在初始化方法上。生命周期有关
h、@PreDestroy(了解)
作用:用在销毁方法上。生命周期有关
i、@Configuration和@Bean(了解)
作用:@Configuration指定当前类为配置类,用于加载@Bean的定义。@Bean用于定义bean的名称,用法是@Bean(name="beanName")
注意:该类要被设置在注解自动扫描对应的包下。

6.3、Spring中使用单元测试

a、导入jar包:
spring-test-3.2.0.RELEASE.jar
b、设置Junit运行器和Spring配置文件

步骤:

0、编写一个类(dao层)

package springIoc.dao;

import org.springframework.stereotype.Component;

/**
 * @Component是spring的一个注解,它是把XXDao1看做一个组件。
 * 就相当于xml中 
 * @author mch
 *
 */
@Component(value="xxDao1")
public class XXDao1 {


	public void save() {
		System.out.println("SPRING3.XIOC成功了");
	}
}
1、设置是spring配置文件



      
		
2、进行编写测试类。进行测试

package springIoc.dao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)//指定新的运行器,该运行前会初始化Spring容器,并注入资源,执行Junit单元测试
@ContextConfiguration(locations={"classpath:springIoc/springxml.xml"})//指定spring容器要加载的配置文件
public class XXDao1Test {

	@Autowired
	private XXDao1 xxDao1;
	
	@Test
	public void test1(){
		xxDao1.save();
	}
}
结果成功!

总结:

其实spring的Ioc原理是 IOC原理:工厂 + 反射 + 配置文件.

spring框架(二)——spring概述与spring的核心之IOC_第14张图片

那么Spring的Ioc就说到这,后面在继续了解它。

你可能感兴趣的:(spring框架(二)——spring概述与spring的核心之IOC)