Spring 源碼閱讀-BeanFactory

#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體系圖

輸入圖片說明

相關文章
相關標籤/搜索