Spring学习5(2)BeanFactory和ApplicationCotext

本文详细介绍了Spring框架中的BeanFactory和ApplicationContext。BeanFactory作为IoC容器的基础,提供类的通用工厂功能,而ApplicationContext则在此基础上增加了更多面向应用的功能。文中探讨了BeanFactory的类体系结构和初始化过程,以及ApplicationContext的类结构、基本初始化方法,包括类注解配置和基于Groovy DSL的配置。同时,文章还讲解了WebApplicationContext在Web应用中的使用和初始化方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring学习5(2)

基本介绍

 Spring通过配置文件来描述Bean和Bean之间的依赖关系,利用java来对Bean实例化并建立Bean之间的依赖关系。
 BeanFactory是spring框架最核心的接口,它提供了高级IoC的配置机制,它使管理不同类型的java对象成为可能。
 ApplicationContext建立在BeanFactory基础之上,提供了更多面向应用的功能,更易于创建实际应用。
 一般称BeanFactory为IoC容器,而ApplicationContext为应用上下文,但有时也叫ApplicationContext为spring容器。
 对于二者的区别是BeanFactory是spring框架的基础,面向spring本身;ApplicationContext面向spring框架的开发者,基本开发场景都使用ApplicationContext。

BeanFactory

 beanfactory是一个类工厂,但和传统的类工厂不同,它是类的通用工厂,所有可以被spring容器实例化并管理的java类都可以成为spring的bean。

BeanFactory的类体系结构

 BeanFactory是不断的继承发展而来从而形成了一个类的结构树,BeanFactory这个接口就位于类结构树的顶端,其主要方法就是getBean(String beanName)来获得特定名称的Bean。它的功能通过其他接口而不断的扩展。
 下面这张图是书中给出的结构图:
在这里插入图片描述

 这其中有如下的接口:

  1. ListableBeanFactory:定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数,容器中是否包含这某一个特定的Bean等。
  2. HierarchicalBeanFactory:父子级联IoC容器的接口,子容器可以通过接口访问父容器。
  3. ConfigurableBeanFactory:增强了IoC容器的可定制性,定义了设置类装载器,属性编辑琦等方法。
  4. AutoWirecapableBeanFactory:定义了将容器中的Bean按某种规则进行自动装配的方法。
  5. SingletonBeanRegistry:定义了允许在运行期间向容器注册单实例Bean的方法。
  6. BeanDefinitionRegistry:Spring配置文件中的每一个<bean>节点元素在spring容器中都通过一个BeanDefinition对象表示,它描述了Bean的配置对象信息。而这个接口提供了向容器手工注册BeanDefinition对象的方法。

初始化BeanFactory

 使用spring配置文件来提供配置信息,然后通过BeanFactory装配配置文件,最后启动springIoC容器。
 这里我们通过上一节Car的例子来说明。首先将Car放到com.smart包下,在resourcecs/com/smart/beanfactory下创建beans.xml文件进心配置,其中代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<bean id="car1" class="com.smart.Car"
	p:brand="红旗CA72"
	p:color="黑色"
	p:maxSpeed="200"
	/>
	</beans>

 接下来就是利用BeanFactory来实现容器的启动,这里注意的是不要用XmlBeanFactory了,这个接口已经被弃用了,我们使用XmlBeanDefinitionReader,DefaultListableBeanFactory实现类启动spring的IoC容器。代码如下:

package com.smart.beanfactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import com.smart.Car;
import org.testng.annotations.*;
import static org.testng.Assert.*;
public class BeanFactoryTest{
	
	@Test
	public void getBean()throws Throwable{
		ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		Resource res = resolver.getResource("classpath:com/smart/beanfactory/beans.xml");
		System.out.println(res.getURL());
		DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
		reader.loadBeanDefinitions(res);
		
		Car car = factory.getBean("car1", Car.class);
		car.introduce();
	}
}

 这里XmlBeanDefinitionReader通过Resource装载配置信息而后就可以通过BeanFactory.getBean(beanName)来获取Bean,并且启动容器,不过此时不会去初始化Bean,只有在调用后才会初始化,对于单实例的Bean,BeanFactory会缓存实例。
 在初始化BeanFactory时,必须提供一种日志框架,书中采用Log4J的形式否则容器会报错。
 注意这里getBean获取的是"car1"也就是和xml中对应起来。

ApplicationContext介绍

 如果说BeanFactory是Spring的心脏那么ApplicationContext就是spring的身躯。很多在BeanFactory中以编程实现的功能在ApplicationContext中都能用配置的方式的实现。

ApplicationContext类体系结构

 ApplicationContext的主要实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者是靠类路径来加载,后者是利用系统路径来加载。
 同样于BeanFactory,ApplicationContext有一个类继承体系,不过在经历了上一小节的学习后,个人认为这个暂时还是先看看就好,下面给出书上的图:
在这里插入图片描述

基本初始化

 和BeanFactory初始化类似,ApplicationContext的初始化也很简单代码如下:(代码中beans的位置可以自己创建文件夹而后把上一节的beans中的内容分配过去)

package com.smart.context;
import org.testng.annotations.*;

import com.smart.Car;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.testng.Assert.*;

public class ApplicationContextTest{
	@Test
	public void getBean() throws Throwable{
		ApplicationContext ctx1 =
				new ClassPathXmlApplicationContext("com/smart/context/beans.xml");
		ApplicationContext ctx2 = 
				new FileSystemXmlApplicationContext("E:/work_java/chapter4/src/main/resources/com/smart/context/beans.xml");
		Car car1 = ctx1.getBean("car1", Car.class);
		car1.introduce();
		Car car2 = ctx2.getBean("car1", Car.class);
		car2.introduce();
	}
}

注意这里的路径都是自动加上"classpath:"和“file:”前缀的,当然也可以手动加上去。
 这里有一个坑点就是你要理解"file:"的含义,它是关于系统的路径,千万不要和书上那样去和类路径写成一样。

 除此之外,同样也可以指定一组配置文件,Spring会自动将多个配置文件在内存中整合成一个配置文件,代码如下:

ApplicationContext cxt3 = 
				new ClassPathXmlApplicationContext(
					new String[]{"com/smart/beans1.xml","com/smart/beans2.xml"});

 注意这两个配置文件中的Bean id不能相同,例如我在复制过去以后将一份代码中的car1改成了car2
 ApplicationContext和BeanFactory的初始化和函数虽然类似但是其有一个重大区别,ApplicationContext会在初始化应用上下文的时候就实例化所有的单实例Bean。

类注解配置

 spring目前还支持基于类注解的配置方式,其来源于spring的JavaConfig。利用@Configuration标注就可以提供所需要的配置。
 直接在com.smart.context包下(这些个包也自己创建,下面不再提醒)创建Beans.java,其中代码如下:

package com.smart.context;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.smart.Car;

@Configuration
public class Beans{
	@Bean(name = "car3")
	public Car buildCar() {
		Car car = new Car();
		car.setBrand("红旗CA72");
		car.setMaxSpeed(200);
		return car;
	}
}

 对于这种注解类的配置,spring提供了专门的实现类:AnnotationConfigApplicationContext,其初始化以及测试代码如下:

ApplicationContext cxt4 = 
				new AnnotationConfigApplicationContext(Beans.class);
		Car car3 = cxt4.getBean("car3", Car.class);
		assertNotNull(car3);//断言是否为空
		car3.introduce();
基于Groovy DSL的配置

 Spring4.0支持使用Groovy DSL来进行配置,使用Groovy脚本语言,实现及其灵活的配置逻辑。
 首先需要在pom.xml中添加依赖:

      <dependency>
      	<groupId>org.codehaus.groovy</groupId>
      	<artifactId>groovy-all</artifactId>
      	<version>${groovy.version}</version>
      </dependency>

 我们在resourcs/com/smart/context创建groovy-beans.groovy,代码如下:

package com.smart.context;
import com.smart.Car;

beans{
	car5(Car){//名字(类型)
		brand = "红旗CA72"
		maxSpeed = "200"
		color = "red"
	}
}

 spring为基于Groovy的配置提供了专门的ApplicationContext实现类:GenericGroovyApplicationContext,其初始化代码如下:

	ApplicationContext ctx5 = 
				new GenericGroovyApplicationContext("com/smart/context/groovy-beans.groovy");
		Car car5 = (Car) ctx5.getBean("car5");

WebApplicationContext类体系结构

 WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录的路径中装载配置文件。
 从WebApplicationContext中可以获得ServletContext的引用,将整个web应用上下文对象作为属性放置到ServletContext中,以便Web应用环境访问。
 为此spring专门提供了一个工具类WebApplicationContextUtils,通过该类的getWebApplicationContext(ServletContext sc)方法就可以获取WebApplicationContext实例了,示例代码如下:

WebApplicationContext wac = (WebApplicationContext)servletContext
.getAttribute(
WebApplicationContext
.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

 在Web应用环境下,Bean比普通的环境多了三个新的作用域:request,session,global session。

WebApplicationContext初始化

 WebApplicationCOntext的初始化方式和上述其它两种不同,因为WebApplicationContext需要ServletContext实例,即是它必须在拥有Web容器的前提下才能完成或启动工作。我们可以在web.xml中配置自启动的Servlet或定义Web容器监听器(ServletContextListener)来完成启动工作。

启动方式

 spring提供了org.springframework.web.context.ContextLoaderListernerorg.springframework.web.context.ContextLoaderServlet来支持Web容器监听器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 指定配置文件 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/smart-dao.xml, /WEB-INF/smart-service.xml
	</param-value>
</context-param>

<!-- 1.声明Web容器监听器 -->
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>

<!--  2.申明自启动的Servlet-->
<servlet>
	<servlet-name>
		springContextLoaderServlet
	</servlet-name>
	<servlet-class>
		org.springframework.web.context.ContextLoaderServlet
	</servlet-class>
	<!-- 启动顺序 -->
	<load-on-startup>1</load-on-startup>
</servlet>
</web-app>

 可以通过Web容器上下文参数contextConfigLocation获取spring配置文件的位置并且可以指定多个配置文件,可以用逗号,空格或者冒号分开即可表示。
 这里的配置文件路径是相对于web的部署根目录路径的,当然也可以使用如"classpath"这种更方便的格式。

日志配置文件

 由于WebApplicationContext需要日志共能,所以我们需要把Log4J的配置文件放置到WEB-INF/classes目录下,这样Log4J可以顺利启动。
 当然,日志配置文件也可以放到其他目录中,不过需要在web.xml中指定文件位置。spring为启动Log4J也提供了两种实现类,不过都需要保证先装载日志文件再装载spring配置文件。示例代码如下:

<!-- 指定Log4J配置文件的位置 -->
<context-param>
	<param-name>log4jConfigLocation</param-name>
	<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<!-- 装载Log4J配置文件的自启动Servlet -->
<servlet>
	<servlet-name>log4jConfigServlet</servlet-name>
	<servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
<!--  2.申明自启动的Servlet-->
<servlet>
	<servlet-name>
		springContextLoaderServlet
	</servlet-name>
	<servlet-class>
		org.springframework.web.context.ContextLoaderServlet
	</servlet-class>
	<!-- 启动顺序 -->
	<load-on-startup>2</load-on-startup>
</servlet>

 注意这里的<load-on-startup>就代表着装载顺序如果是Listerner来配置就要将Log4J的配置放在ContextLoaderListener之前。

使用@Configuration配置时的启动

 如果采用@Configuration进行配置,需要通过指定context参数,让Springs使用AnnotationConfigWebApplicationContext而不是xmlWebApplicationContext进行配置,那么web.xml的配置代码如下:

<context-param>
	<param-name>contextClass</param-name>
	<param-value>
		org.springframework.web.context.support.AnnotationConfigWebApplicationContext
	</param-value>
</context-param>

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		com.smart.AppConfig1, com.smart.AppConfig2
	</param-value>
</context-param>

<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>
Groovy配置启动

 与使用注解的方式类似,只不过在contextClass的配置中将<param-value>的值改成org.springframework.web.context.support.GroovyWebApplicationContext

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值