#Spring 源碼閱讀(一)java
##一.環境準備 IDEA+Maven+Jetty。web
pom.xml代碼spring
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Test2</groupId> <artifactId>Test2</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>Test2 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.1.6.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>3.3.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.6</version> </dependency> </dependencies> <!--Jetty插件--> <build> <finalName>Test2</finalName> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>7.6.10.v20130312</version> <configuration> <webAppSourceDirectory>${basedir}/webapp</webAppSourceDirectory> <stopKey>stop</stopKey> <stopPort>5580</stopPort> <scanIntervalSeconds>0</scanIntervalSeconds> <connectors> <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector"> <port>8080</port> <maxIdleTime>60000</maxIdleTime> </connector> </connectors> <webAppConfig> <contextPath>/</contextPath> </webAppConfig> <systemProperties> <systemProperty> <name>global.config.path</name> <value>${basedir}/src/main/resources/config</value> </systemProperty> </systemProperties> </configuration> </plugin> </plugins> </build> </project>
##二.測試代碼express
Bean類apache
package com.wm; public class People implements Serializable { Integer age; String sex; String name; public String getName() { return name;} public void setName(String name) {this.name = name;} public Integer getAge() {return age;} public void setAge(Integer age) {this.age = age;} public String getSex() {return sex;} public void setSex(String sex) {this.sex = sex;} @Override public String toString(){ StringBuffer stringBuffer=new StringBuffer(); stringBuffer.append("People name:") .append(name) .append(" sex:") .append(sex) .append(" age:") .append(age); return stringBuffer.toString(); } }
Client類api
public class Client { public static void main(String[] args){ ClassPathResource classPathResource=new ClassPathResource("/spring/spring-mvc.xml"); BeanFactory beanFactory=new XmlBeanFactory(classPathResource); People people=(People) beanFactory.getBean("people"); people.setAge(12); people.setName("Lily"); people.setSex("girl"); System.out.println(people.toString()); } }
Spring配置文件數組
<?xml version="1.0" encoding="UTF-8"?> <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="people" class="com.wm.People"></bean> </beans>
輸出結果: People name:Lily sex:girl age:12 ##三.分析 ###3.1 首先根據配置文件名稱獲取ClassPathResource。spring-mvc
1.ClassPathResource代碼mvc
public ClassPathResource(String path) { //類加載設置爲空 this(path, (ClassLoader)null); } public ClassPathResource(String path, ClassLoader classLoader) { Assert.notNull(path, "Path must not be null"); //文件路徑 String pathToUse = StringUtils.cleanPath(path); if(pathToUse.startsWith("/")) { pathToUse = pathToUse.substring(1); } this.path = pathToUse; //若是類加載器爲空獲取默認類加載器 this.classLoader = classLoader != null?classLoader:ClassUtils.getDefaultClassLoader(); }
Spring實現配置文件的解析app
2.Resource接口 Resource其實就是封裝Java的URL
public interface Resource extends InputStreamSource { //文件是否存在 boolean exists(); //文件是否可讀 boolean isReadable(); //文件可否打開 boolean isOpen(); URL getURL() throws IOException; URI getURI() throws IOException; File getFile() throws IOException; long contentLength() throws IOException; long lastModified() throws IOException; Resource createRelative(String var1) throws IOException; String getFilename(); String getDescription(); }
對應不一樣資源來源有不一樣的Resource實現類
3.ByteArrayResource 字節數組資源
//將不可變字節數組轉換爲字符串 public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(this.byteArray); }
4.ClassPathResource 類路徑資源
本資源類的clazz屬性存在,那麼資源相對於這個clazz類相對路徑的。若是不存在,那麼資源類就是相對於整個應用程序的。
//路徑 private final String path; //類加載器 private ClassLoader classLoader; //所屬類 private Class<?> clazz; public InputStream getInputStream() throws IOException { InputStream is; //若是所屬類不爲空,則調用所屬類的getResourceAsStream if(this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); } else if(this.classLoader != null) { is = this.classLoader.getResourceAsStream(this.path); } else { is = ClassLoader.getSystemResourceAsStream(this.path); } if(is == null) { throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist"); } else { return is; } } public URL getURL() throws IOException { URL url = this.resolveURL(); if(url == null) { throw new FileNotFoundException(this.getDescription() + " cannot be resolved to URL because it does not exist"); } else { return url; } }
###3.2 BeanFactory beanFactory=new XmlBeanFactory(classPathResource);
1.XmlBeanFactory代碼
private final XmlBeanDefinitionReader reader; public XmlBeanFactory(Resource resource) throws BeansException { this(resource, (BeanFactory)null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader = new XmlBeanDefinitionReader(this); this.reader.loadBeanDefinitions(resource); }
2.BeanFactory 有三個子類接口:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory,還有一個實現類SimpleJndiBeanFactory。
BeanFactory代碼
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; //獲取實例 Object getBean(String var1) throws BeansException; <T> T getBean(String var1, Class<T> var2) throws BeansException; <T> T getBean(Class<T> var1) throws BeansException; Object getBean(String var1, Object... var2) throws BeansException; <T> T getBean(Class<T> var1, Object... var2) throws BeansException; //是否已經包含Bean boolean containsBean(String var1); //是否單例 boolean isSingleton(String var1) throws NoSuchBeanDefinitionException; //是不是原型(多實例) boolean isPrototype(String var1) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException; //獲取類型 Class<?> getType(String var1) throws NoSuchBeanDefinitionException; //獲取別名 String[] getAliases(String var1); }
3.ListableBeanFactory代碼 能夠列出工廠能夠生產的全部實例
public interface ListableBeanFactory extends BeanFactory { boolean containsBeanDefinition(String var1); int getBeanDefinitionCount(); //返回工廠中全部Bean的名稱 String[] getBeanDefinitionNames(); //對於給定的名字有多少份BeanDefinition 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); //根據註解類型,查找全部有這個註解的Bean名和Bean的Map Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> var1) throws BeansException; //根據指定Bean名和註解類型查找指定的Bean <A extends Annotation> A findAnnotationOnBean(String var1, Class<A> var2) throws NoSuchBeanDefinitionException; }
4.AutowireCapableBeanFactory代碼 自動裝配 這個工廠接口繼承自BeanFacotory,它擴展了自動裝配的功能,根據類定義BeanDefinition裝配Bean、執行前、後處理器等。
public interface AutowireCapableBeanFactory extends BeanFactory { //這個常量代表工廠沒有自動裝配的Bean int AUTOWIRE_NO = 0; //根據名稱自動裝配 int AUTOWIRE_BY_NAME = 1; //根據類型自動裝配 int AUTOWIRE_BY_TYPE = 2; //根據構造方法裝配 int AUTOWIRE_CONSTRUCTOR = 3; [@Deprecated](http://my.oschina.net/jianhuaw) int AUTOWIRE_AUTODETECT = 4; <T> T createBean(Class<T> var1) throws BeansException; void autowireBean(Object var1) throws BeansException; //根據Bean名的BeanDefinition裝配這個未加工的Object,執行回調和各類後處理器。 Object configureBean(Object var1, String var2) throws BeansException; Object resolveDependency(DependencyDescriptor var1, String var2) throws BeansException; Object createBean(Class<?> var1, int var2, boolean var3) throws BeansException; Object autowire(Class<?> var1, int var2, boolean var3) throws BeansException; void autowireBeanProperties(Object var1, int var2, boolean var3) throws BeansException; void applyBeanPropertyValues(Object var1, String var2) throws BeansException; Object initializeBean(Object var1, String var2) throws BeansException; Object applyBeanPostProcessorsBeforeInitialization(Object var1, String var2) throws BeansException; Object applyBeanPostProcessorsAfterInitialization(Object var1, String var2) throws BeansException; //銷燬bean void destroyBean(Object var1); //分解指定的依賴 Object resolveDependency(DependencyDescriptor var1, String var2, Set<String> var3, TypeConverter var4) throws BeansException; }
5.HierarchicalBeanFactory代碼 分層Bean工廠。從這個接口開始,BeanFactory有了雙親Factory,父Factory的概念。
public interface HierarchicalBeanFactory extends BeanFactory { 返回父工廠 BeanFactory getParentBeanFactory(); //查看當前工廠是否包含Bean boolean containsLocalBean(String name); }
直接子接口共有兩個,一個是ApplicationContext,還有一個是ConfigurableBeanFactory。
總結:
1.一級接口爲BeanFactory
2.三個繼承他的接口,HierarchicalBeanFactory,AutowireCapableBeanFactory,ListableBeanFactory,可稱爲二級接口
三、ConfigurableBeanFactory能夠被稱爲三級接口,對二級接口HierarchicalBeanFactory進行了再次加強,它還繼承了另外一個外來的接口SingletonBeanRegistry
四、ConfigurableListableBeanFactory是一個更強大的接口,繼承了上述的全部接口,無所不包,稱爲四級接口。
(這4級接口是BeanFactory的基本接口體系。繼續,下面是繼承關係的2個抽象類和2個實現類:)
五、AbstractBeanFactory做爲一個抽象類,實現了三級接口ConfigurableBeanFactory大部分功能。
六、AbstractAutowireCapableBeanFactory一樣是抽象類,繼承自AbstractBeanFactory,並額外實現了二級接口AutowireCapableBeanFactory
七、DefaultListableBeanFactory繼承自AbstractAutowireCapableBeanFactory,實現了最強大的四級接口ConfigurableListableBeanFactory,並實現了一個外來接口 BeanDefinitionRegistry,它並不是抽象類。
八、最後是最強大的XmlBeanFactory,繼承自DefaultListableBeanFactory,重寫了一些功能,使本身更強大。提供了Xml文件相關BeanFactory的方法。能夠讀取xml定義的BeanDefinition文件。
BeanFactory體系圖