一、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>