Spring入门2——XML篇

本文介绍了Spring框架中XML配置的基本用法,包括bean的声明、接口与实现类的映射、引用关系的建立以及构造和设值注入。同时,讲解了Spring bean的生命周期、作用域以及初始化和销毁方法。最后提到了通过JUnit测试配置的正确性,并简要说明了通过Maven管理项目及获取Spring上下文的方法。

一般来说,业务逻辑是分层的

假设我们现在有服务层和持久层。

持久层IDao和实现类DaoImpl:

public interface IDao {
	public void save(String data);
}

public class DaoImpl implements IDao {

	public void save(String data) {
		System.out.println("save to database:" + data);
	}

}

服务层接口IService和实现类ServiceImpl

public interface IService {
	public void save(String data);
}
public class ServiceImpl implements IService {
	
	private IDao iDao;

	public void setiDao(IDao iDao) {
		this.iDao = iDao;
	}

	public void save(String data) {
		System.out.println("sovle data");
		iDao.save(data);
	}

}
可以看到,其ServiceImpl类中存在对持久层IDao的引用。也就是说ServiceImpl中存在IDao这个对象。Service通过调用持久层的方法来保存数据的意思。


所以,这么一种关系通过配置文件应该怎么表示呢?我们想要表达我们有两个接口,而接口的实现类也分别给出了,并且接口之间存在引用的关系。


首先是我们有两个接口IService和IDao,他们的实现类分别是ServiceImpl和DaoImpl。我们要表达这么一个关系。

在配置文件中,我们就需要这么做:

<bean id="iService" class="Spring.test1.ServiceImpl"></bean>

<bean id="iDao" class="Spring.test1.DaoImpl"></bean>
在Spring容器中,所有对象都称为bean对象。
所以两个接口分别对应两个bean标签。

可以看到,id为iService的bean的实现类是Spring.test1.ServiceImpl这个类。id为iDao的bean的实现类是Spring.test1.DaoImpl这个类。

这和我们一开始的期望是一样的。(当然,如果不使用面向接口的方式,单独的类的实现也可以是这么一个方式)

在我看到,这是这么一个意思:可以通过bean的id名,返回一个class对应的包的对象给我(而这个对象是否是新创建的取决于我们的配置,默认是单例)。


而bean之间是存在引用关系的,这怎么表达呢?

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id = "iService" class = "Spring.test1.ServiceImpl">
		<property name = "iDao" ref = "iDao"></property>
	</bean>
	
	<bean id = "iDao" class = "Spring.test1.DaoImpl"></bean>
	
</beans>

这是其中一种方式,通过ref属性可以找到对应的bean名称并调用对应的方法去初始化引用的对象。

上面的配置是通过设值注入的方式初始化的。

也就是说,如果使用property标签,则引用对象的那个类,在这里我们是ServiceImpl类,必须实现引用对象的set方法,property标签会自动调用类中的set方法为引用对象进行初始化。

另一种方式是构造注入,只需要将property标签替换成如下语句:

<constructor-arg name = "iDao" ref = "iDao"></constructor-arg>
并且ServiceImpl对象必须实现构造函数的初始化,也就是说SercieImpl需要增加如下的构造函数:

public ServiceImpl(IDao iDao) {
	this.iDao = iDao;
}
这是两种依赖注入的方式。因为ServiceImpl依赖于iDao实现它的功能,所以需要注入iDao的值。


bean标签还有很多其他的属性。

<beans>标签(Spring配置文件的根元素,包含一个或多个bean元素):

1.default-autowire属性:默认的bean自动装配模式。
  1) no:不使用自动装配。bean的引用必须通过ref元素定义。这是默认的属性
  2) byName:通过属性名字进行自动装配。
  3) byType:如果BeanFactory中正好有一个同属性类型一样的bean,就自动装配这个属性。如果有多于一个这样的bean,就抛出一个致命异常,它指出你可能不能对那个bean使用byType的自动装配。如果没有匹配的bean,则什么都不会发生,属性不会被设置。
  4) constructor:这个同byType类似,不过是应用于构造函数的参数。如果在BeanFactory中不是恰好有一个bean与构造函数参数相同类型,则一个致命的错误会产生。


<bean>标签:
1.id属性:IoC容器中bean的唯一标识符,不允许重复。
2.class属性:bean的类名。我的理解是让容器知道从哪里去获取对象。
3.scope属性:定一个bean的作用域。有5中取值。
  1) singleton。默认的scope,同一个IoC容器中仅存在一个bean实例,是单例。
  2) prototype。每次获取bean对象时,都返回一个新的实例,相当于每次都new一个新的对象。
  3) request。用于web开发,该作用域仅适用于WebApplicationContext。每次HTTP请求都会创建一个Bean中。
  4) session。同样用于web开发,同一个session共享一个bean对象。
  5) globalSession。用于分布式系统,跨系统的时候也能共享bean对象。如果不是portlet环境,等同于session。
4.init-method和destroy-method属性:Spring在初始化bean或销毁bean时候,会分别调用这两个属性的对应的方法。
例如:

<bean id=“foo” class=“...Foo” init-method=“setup” destory-method=“teardown”/>
初始化阶段如果对应的Foo类中有setup方法的话,就会调用setup方法。销毁阶段也一样,调用teardown方法。


顺便提一下Spring的生命周期。Spring的生命周期分为四个阶段:1.定义 2.初始化 3.使用 4.销毁
初始化对应上下文的start方法,销毁对应这上下文的destroy方法。这个在下文的Junit测试中有使用。


现在我们需要的业务逻辑已经写的差不多了。

接下来通过Junit来测试我们的配置是否成功。

这里我通过maven来管理项目。(eclipse j2ee版本好像是自带maven的)

首先创建一个maven项目。

因为需要使用Junit和Spring framework,所以我们在pom配置中加入以下依赖。

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<springframework.version>4.3.3.RELEASE</springframework.version>
</properties>

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.8.1</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>${springframework.version}</version>
		<scope>compile</scope>
	</dependency>
</dependencies>


之后我们就开始编写我们的测试文件了。

这里直接上代码吧

package Spring.test1;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
	
	private ClassPathXmlApplicationContext context;
	
	@Before
	public void before() {
		try {
			context = new ClassPathXmlApplicationContext("classpath:spring-ioc.xml");
			context.start();
		} catch (BeansException e) {
			e.printStackTrace();
		}
	}
	
	@After
	public void after() {
		context.destroy();
	}
	
	@Test
	public void Test() {
		IService iService = (IService) context.getBean("iService");
		iService.save("myData");
	}
	
}
这里需要说明一下,我们在获取的bean的时候,需要通过Spring容器的应用上下文来获取,指明是获取哪个上下文的bean。所以我们就需要先获取上下文,就是@Before模块中所示。spring-ioc.xml是我们之前写的配置文件。而classpath是什么呢?

classpath是资源文件目录,在maven中是src/main/resources目录,spring-ioc.xml存放在这个目录下。

因为我们需要spring-framework的上下文,所以我们能看到,在pom配置文件中,有关于context的依赖。


bean容器的初始化,也就是上下文的获取,是有三种方式的。

1.通过本地文件来获取:

例如:

FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("文件路径");

2.通过ClassPath来获取:

就如同样例所示。

3.通过web来获取:

这个方法比较不一样,在我们的web应用中,我们在web.xml文件中进行配置。

通过listener或servlet来获取。

下面是listener的例子:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


这个时候我们应该理解了上下文的定义了。

如果我们希望在类中获取Ioc容器的bean的信息怎么办呢?

我们可以通过实现ApplicationContextAware这个接口来完成。

例子:

public class AwareTest implements ApplicationContextAware {

	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		((IService)arg0.getBean("iService")).save("myData2");
	}
	
}
只需要实现这个接口,就可以拿到我们的上下文了,当然这需要在配置文件中进行配置。

还有许许多多的Aware接口,大家可以自己去查找,例如BeanFactoryAware,ResourceLoaderAware等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值