一、BeanFactory接口java
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的子接口ListableBeanFactoryweb
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
经过这个接口Spring的IoC容器能够创建父子层级关联的容器体系,子容器能够访问父容器中的Bean,但父容器不能访问子容器中的Bean。数据库
package org.springframework.beans.factory; public interface HierarchicalBeanFactory extends BeanFactory { // 得到父级的BeanFactory BeanFactory getParentBeanFactory(); boolean containsLocalBean(String var1); }
AutowireCapableBeanFactory接口apache
定义了自动装配api
DefaultSingletonBeanRegistry接口缓存
DefaultSingletonBeanRegistry里有一个addSingleton()方法,会把单例的Bean保存到一个ConcurrentHashMaptomcat
// 缓存到一个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 实现类session
这个类实现了上面全部的接口app
<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...");
}
}
三、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>
四、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>