spring容器、BeanFactory、ApplicatContext、WebApplicationContext

1、BeanFactory接口

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType; public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
// getBean()方法从容器中返回Bean
Object getBean(String var1) throws BeansException; <T> T getBean(String var1, Class<T> var2) throws BeansException; Object getBean(String var1, Object... var2) throws BeansException; <T> T getBean(Class<T> var1) throws BeansException; <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
// 容器里有没有一个Bean
boolean containsBean(String var1);
// 一个Bean是不是单例的
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
// 一个Bean是不是复例的
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException; Class<?> getType(String var1) throws NoSuchBeanDefinitionException; String[] getAliases(String var1);
}

BeanFactory的子接口ListableBeanFactory

package org.springframework.beans.factory;

import java.lang.annotation.Annotation;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType; public interface ListableBeanFactory extends BeanFactory {
// BeanDefinition
boolean containsBeanDefinition(String var1);
// BeanDefinition
int getBeanDefinitionCount();
// BeanDefinition
String[] getBeanDefinitionNames(); String[] getBeanNamesForType(ResolvableType var1); String[] getBeanNamesForType(Class<?> var1); String[] getBeanNamesForType(Class<?> var1, boolean var2, boolean var3); <T> Map<String, T> getBeansOfType(Class<T> var1) throws BeansException; <T> Map<String, T> getBeansOfType(Class<T> var1, boolean var2, boolean var3) throws BeansException; String[] getBeanNamesForAnnotation(Class<? extends Annotation> var1); Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> var1) throws BeansException; <A extends Annotation> A findAnnotationOnBean(String var1, Class<A> var2) throws NoSuchBeanDefinitionException;
}

BeanFactory的子接口HierarchicalBeanFactory  [ˌhaɪəˈrɑːkɪkl] 

通过这个接口Spring的IoC容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的Bean,但父容器不能访问子容器中的Bean。

package org.springframework.beans.factory;

public interface HierarchicalBeanFactory extends BeanFactory {
// 获得父级的BeanFactory
BeanFactory getParentBeanFactory(); boolean containsLocalBean(String var1);
}

AutowireCapableBeanFactory接口

定义了自动装配

DefaultSingletonBeanRegistry接口

DefaultSingletonBeanRegistry里有一个addSingleton()方法,会把单例的Bean保存到一个ConcurrentHashMap

    // 缓存到一个map里
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256); protected void addSingleton(String beanName, Object singletonObject) {
Map var3 = this.singletonObjects;
synchronized(this.singletonObjects) {
// 添加单对象到map
this.singletonObjects.put(beanName, singletonObject != null ? singletonObject : NULL_OBJECT);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

DefaultListableBeanFactory 实现类

这个类实现了上面所有的接口

<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="tank" class="my.Tank"></bean> </beans>
package my;

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 java.io.IOException; public class MyTest {
public static void main(String[] args) throws IOException {
// 创建一个资源加载器
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 使用ClassPathResource加载配置文件
Resource resource = resolver.getResource("classpath:my.xml"); // 创建一个BeanFactory的对象
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource); // 单例的Bean已经缓存到容器中
Tank tank = (Tank)factory.getBean(Tank.class);
tank.run();
}
}
class Tank {
public void run() {
System.out.println("run...");
}
}

3、ApplicatContext接口

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {}

ApplicationContext继承了ListableBeanFactory、HierarchicalBeanFactory,另外还通过其它几个接口扩展了BeanFactory的功能。

ApplicationEventPublisher让spring容器拥有发布事件的功能,包括spring容器启动、关闭。ApplicationContext基于Observer模式(java.util包中有对应实现),提供了针对Bean的事件传播功能。事件传播的一个典型应用是,当Bean中的操作发生异常(如数据库连接失败),则通过事件传播机制通知异常监听器进行处理。

ResourcePatternResolver,所有的ApplicationContext实现类都实现了类似于PathMatchingResourcePatternResolver的功能,可以通过文件路径装载spring配置文件。

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import java.io.IOException; public class MyTest {
public static void main(String[] args) throws IOException {
// 使用ClassPathXmlApplicationContext可以省略路径字符串的classpath前缀
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:my.xml");
//AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Tank tank = context.getBean(Tank.class); tank.run();
}
}
class Tank {
public void run() {
System.out.println("run...");
}
}
@Configuration
class MyConfig{
@Bean
public Tank tank() {
return new Tank();
}
}
<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="tank" class="my.Tank"></bean> </beans>

4、WebApplicationContext

WebApplicationContext是专门为web应用准备的。

WebApplicationContext源码:

package org.springframework.web.context;

import javax.servlet.ServletContext;
import org.springframework.context.ApplicationContext; public interface WebApplicationContext extends ApplicationContext {
/**
* WebApplicationContext作为属性保存到了ServletContext中,Spring为此专门提供了一个工具类WebApplicationContextUtils,
* 通过该类的getWebApplicationContext(ServletContext sc)方法,可以从ServletContext中获取WebApplicationContext的实例。
*
* 常量ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE是在ServletContext中保存WebApplicationContext的key
* 可以通过以下方法获得WebApplicationContext的实例
* WebApplicationContext context =
* (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
*
* 这也正是WebApplicationContextUtils的getWebApplicationContext(ServletContext sc)方法的内部实现方式。
*/
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
/**
* 在非web应用的环境下,Bean只有singleton和prototype两种作用域。
* WebApplicationContext为Bean添加了三个新的作用域:
* 分别是request、sesseion和global sesseion。
*/
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_GLOBAL_SESSION = "globalSession";
String SCOPE_APPLICATION = "application";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
// 也可以WebApplicationContext中获取ServletContext
ServletContext getServletContext();
}

ConfigurableWebApplicationContext源码:

package org.springframework.web.context;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.context.ConfigurableApplicationContext; public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() + ":"; String SERVLET_CONFIG_BEAN_NAME = "servletConfig"; void setServletContext(ServletContext var1); void setServletConfig(ServletConfig var1); ServletConfig getServletConfig(); void setNamespace(String var1); String getNamespace();
// 设置配置文件地址,允许通过配置文件实例化WebApplicationContext
void setConfigLocation(String var1); void setConfigLocations(String... var1); String[] getConfigLocations();
}

XmlWebApplicationContext、AnnotationConfigWebApplicationContext这两个类都实现了上面的接口

但WebApplicationContext的初始化方式和BeanFactory、ApplicationContext不一样,因为它们必须在拥有Web容器的前提下才能启动。使用XmlWebApplicationContext或AnnotationConfigWebApplicationContext实例化WebApplicationContext需要在web.xml中定义监听器ContextLoaderListener。ContextLoaderListener通过ServletContext参数contextConfigLocation获取Spring配置文件的位置,用户可以指定多个配置文件,用逗号、空格或冒号分隔均可。

package com.test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet("/run")
public class MyTest extends HttpServlet {
private Tank tank; public void setTank(Tank tank) {
this.tank = tank;
} protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
WebApplicationContext context = (WebApplicationContext) req.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
MyTest myTest = context.getBean(MyTest.class);
myTest.tank.run();
}
}
class Tank {
public void run() {
System.out.println("run ...");
}
}
@Configuration
class MyConfig {
// 这个方法随便声明、方法参数随便写,因为这是一个新的方法,在这个方法的内部调用其它方法
@Bean
public MyTest myTest(Tank tank) {
MyTest myTest = new MyTest();
myTest.setTank(tank);
return myTest;
}
@Bean
public Tank tank() {
return new Tank();
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="tank" class="com.test.Tank"/> <bean id="myTest" class="com.test.MyTest" p:tank-ref="tank"/> </beans>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>spring-demo</display-name>
<!--让spring使用AnnotationConfigWebApplicationContext而非XmlWebApplicationContext启动容器
如果想使用XmlWebApplicationContext,不需要下面这个<context-param>的配置
-->
<!--<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.test.MyConfig</param-value>-->
<param-value>classpath:/my.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.test.spring</groupId>
<artifactId>spring-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging> <name>spring-demo</name> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
</dependencies> <build>
<finalName>spring-demo</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>80</port>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
上一篇:java进阶书籍推荐(不包括基础)


下一篇:html5+js压缩图片上传