首页 > 程序开发 > 软件开发 > 其他 >

Spring框架学习总结

2016-10-08

Spring框架框架的核心功能有两个:Spring容器作为超级大工厂,负责创建、管理所有的java对象,这些java对象被称作Bean。Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称作“依赖注入”的方式来管理Bean之间的依赖关系。

Spring框架框架的核心功能有两个:

Spring容器作为超级大工厂,负责创建、管理所有的java对象,这些java对象被称作Bean。Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称作“依赖注入”的方式来管理Bean之间的依赖关系。

1 IOC和DI

IOC(Inversion of Control):其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器实时的返回资源。而应用了IOC之后,则是容器主动的将资源推送给它所管理的组件,组件要做的则是选择一种合适的方式来接受资源。这种行为也成为被查找的被动形式。

DI(Depedency Injection):IOC的另一种表达方式,即组件以一些预先定义好的方式(例如:setter方法)接受来自容器的资源注入。相对于IOC而言,这种表述更直接。

2 IOC的发展历程

举一个例子,需求是需要生成一个HTML和PDF的不同类型的报表。以前我们一般会这样做,如UML类图1所示:

\

图1

service层依赖ReportGenrator接口,pdf和html的Generator去实现ReportGenrator接口,然后ReportService去关联PdfReportGenerator类和HtmlReportGenerator类。这样子Service层与其报表生成的两个类的耦合度就非常高。发展到后来开发者们开始利用工厂设计模式,service层不再去和PdfReportService和HtmlReportGenerator类去关联,而是去关联ReportGeneratorFactory工厂,由工厂去生产这两个类。当service层需要时向工厂提出需求,有工厂负责生产。如图2所示:

\

图2

发展到今天,Spring采用了IOC即反转控制。此时service层不再需求去主动请求PdfReportGenerator和HtmlReportGenerator的资源,而是有容器Container主动去注入资源,也就是service层被动接受来自Container的资源。service层和PdfReportGenerator、HtmlReportGenerator类无耦合,整个设计的耦合度大大降低。如图3所示:

\

图3

3 在Spring的IOC容器中配置bean

这里以HelloWorld为例,首先给出所有代码,然后再去做一个小结。

package com.alibaba.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main
{
	public static void main(String[] args)
	{
		//创建spring的IOC容器对象
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//从IOC容器中获取bean实例
		HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");

		helloWorld.hello();
	}
}

Bean代码:

package com.alibaba.beans;
public class HelloWorld
{
	private String name;

	public void setName(String name)
	{
		System.out.println("setName: " + name);
		this.name = name;
	}
	
	public void hello()
	{
		System.out.println("hello:" + name);
	}
	
	public HelloWorld()
	{
		System.out.println("HelloWorld's constructor ...");
	}
}

applicationContext.xml代码:



	
	
	    
	

id作为Bean的名称,在IOC容器中必须是唯一的。若id没有指定,则Spring会将类的全限定名作为bean的名字。这里的class即就是bean的全类名,spring会通过反射在IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器。在Main类中的ApplicationContext就是IOC容器,在SpringIOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化才可以从IOC容器中获取bean实例。

4 Spring容器

Spring提供了两种类型的IOC容器实现:

BeanFactory:IOC容器的基本实现。ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口,它增强了BeanFactory的功能。

大部分时候,都不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器。ApplicationContext的主要实现类有两个:

ClassPathXmlApplicationContex:从类路径下加载配置文件。
FileSystemXmlApplicationContext:从文件系统中加载配置文件。

ConfigurableApplicationContext扩展于ApplicationContext,新增加两个主要方法:refresh()和close(),让ApplicationContext具有启动、刷新和关闭上下文的能力。ApplicationContext在初始化上下文时就实例化所有单例的Bean。接下来列出其类的关系图及UML类图,分别如图4、图5所示。

\

图4

\

图5

5 依赖注入的方式

Spring支持的依赖注入主要有两种:属性注入(摄值注入)和构造器注入。属性注入即通过setter方法注入Bean的属性值或依赖的对象。属性注入使用元素,使用name属性指定Bean的属性名称,value属性或子节点指定属性值。属性注入是实际应用中最常用的注入方式。

6 引用其他Bean

在这里我们添加一个Car类和Person类,让Person类去引用Car类。附上Car和Person类的代码。

package com.alibaba.beans;

public class Person
{
	private String name;
	private int age;
	private Car car;

	public String getName()
	{
		return name;
	}

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

	public int getAge()
	{
		return age;
	}

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

	public Car getCar()
	{
		return car;
	}

	public void setCar(Car car)
	{
		this.car = car;
	}

	@Override
	public String toString()
	{
		return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
	}

	
}
package com.alibaba.beans;
public class Car
{
	private String company;
	private String brand;

	private int maxSpeed;
	private float price;

	public Car(String company, String brand, float price)
	{
		super();
		this.company = company;
		this.brand = brand;
		this.price = price;
	}

	public Car(String company, String brand, int maxSpeed)
	{
		super();
		this.company = company;
		this.brand = brand;
		this.maxSpeed = maxSpeed;
	}

	public Car(String company, String brand, int maxSpeed, float price)
	{
		super();
		this.company = company;
		this.brand = brand;
		this.maxSpeed = maxSpeed;
		this.price = price;
	}

	@Override
	public String toString()
	{
		return "Car [company=" + company + ", brand=" + brand + ", maxSpeed=" + maxSpeed + ", price=" + price + "]";
	}
	public Car()
	{
		
	}
}

这样当Person类去引用Car类时,我们的容器里面也得进行配置。applicationContext里面的代码重新更新如下:


	
	
		
	

	
		
		
			]]>
		
		
			250
		
	

	
		
		
		
	


这里我们要实现Person去访问Car,也就是实现Bean之间的互访,就必须在Bean配置文件中指定对Bean的引用。在Bean的配置文件中可以通过元素或者ref属性为Bean的属性或者构造器参数指定对Bean的引用。看到上面我们进行了赋值都是单个属性,其实spring里面支持级联属性,这里需要注意的是在Spring里面需要先初始化后才可以为级联属性赋值,否则会有异常,和Struts2不同。

7 集合属性

为了方便,我们重新建一个包以便我们对集合属性进行学习,这里重新建一个包,其包括了Person类和Main类(以便进行集合属性学习),Person里面的car属性变成了集合,即一个人可以有多辆汽车了,对于Person类和容器中的代码得稍作修改了。现在给出这个包下,Person类和Main类(这个类里面只会去获取Person类的实例)。

package com.alibaba.beans.collections;
import java.util.List;
import com.alibaba.beans.Car;
public class Person
{
	private String name;
	private int age;
	private List cars;

	public String getName()
	{
		return name;
	}

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

	public int getAge()
	{
		return age;
	}

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

	public List getCars()
	{
		return cars;
	}

	public void setCars(List cars)
	{
		this.cars = cars;
	}

	@Override
	public String toString()
	{
		return "Person [name=" + name + ", age=" + age + ", cars=" + cars + "]";
	}

	
}

这个包下的Main类(再次说一遍这个项目里面现在有两个Main类了,运行时只需要点击这个Main类让其运行,我们的目的只是通过这个例子去熟悉集合属性)。

package com.alibaba.beans.collections;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main
{
	public static void main(String[] args)
	{
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person p = (Person) ctx.getBean("person1");
		
		System.out.println(p);
	}
}

此时IOC容器里面的配置稍作修改,主要还是为了学习集合属性。



	
	
		
	

	
		
		
			]]>
		
		
			250
		
	

	
		
		
			]]>
		
		
			260
		
	

	
		
		
		
			
				
				
			
		
	

这里做一个小结:在Spring中可以通过一组内置的xml标签(例如:, )来配置集合属性配置java.util.List类型的属性,需要指定标签,在标签里包含一些元素.这些标签可以通过指定简单的常量值,通过指定对其他Bean的引用.通过指定内置Bean定义.通过指定空元素.甚至可以内嵌其他集合;数组的定义和List一样,都使用;配置java.util.Set需要使用标签,定义元素的方法与List一样。接下来看看Map集合属性的应用。同样为了去学习Map集合属性,需要再次新建一个NewPerson类,然后再applicationContext里面进行更改,最后再第二个新建的Main类中去获取实例进行测试。现在给出代码。

package com.alibaba.beans.collections;

import java.util.Map;
import com.alibaba.beans.Car;
public class NewPerson
{
	private String name;
	private int age;
	private Map cars;

	public String getName()
	{
		return name;
	}

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

	public int getAge()
	{
		return age;
	}

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

	public Map getCars()
	{
		return cars;
	}

	public void setCars(Map cars)
	{
		this.cars = cars;
	}

	@Override
	public String toString()
	{
		return "NewPerson [name=" + name + ", age=" + age + ", cars=" + cars + "]";
	}

}


	
	
		
	

	
		
		
			]]>
		
		
			250
		
	

	
		
		
			]]>
		
		
			260
		
	

	
		
		
		
			
				
				
			
		
	

	
	
		
		
		
				
				
		
	

package com.alibaba.beans.collections;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main
{
	public static void main(String[] args)
	{
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person p = (Person) ctx.getBean("person1");
		
		System.out.println(p);
		System.out.println("---------------------我是分割线-------------------------");
		
		NewPerson np = (NewPerson) ctx.getBean("newPerson");
		System.out.println(np);
	}
}

在此对Map集合属性进行一个小结:(1)Java.util.Map通过标签定义,标签里可以使用多个作为子标签.每个条目包含一个键和一个值;(2)可以将Map的键和值作为的属性定义:简单常量使用key和value来定义;Bean引用通过key-ref和value-ref属性定义;

8 使用p命名空间

为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。Spring从2.5版本开始引入了一个新的p命名空间,可以通过元素属性的方式配置Bean的属性。使用p命名空间后,基于XML的配置方式将进一步简化。下面在容器中新建一个person2的bean,然后使用p命名空间去定义,最后去第二次定义的Main里面获取实例进行测试。下面给出代码。




	
	
		
	

	
		
		
			]]>
		
		
			250
		
	

	
		
		
			]]>
		
		
			260
		
	

	
		
		
		
			
				
				
			
		
	

	
	
		
		
		
				
				
		
	

      
	
	

相关文章
热点推荐