Spring 源碼梳理(六) BeanNameAware和BeanFactoryAware

BeanNameAware和BeanFactoryAware

1.BeanNameAware和BeanFactoryAware概念

BeanNameAware:實現該接口的Bean能夠在初始化時知道自己在BeanFactory中對應的名字。

BeanFactoryAware:實現該接口的Bean能夠在初始化時知道自己所在的BeanFactory的名字。

2.繼續前面文章的分析,看這一段源碼:


initializeBean方法,前面的文章已經分析過了,上圖中的applyBeanPostProcessorsBeforeInitialization也分析了。 這個invokeAwareMethods就是對繼承Aware接口的Bean進行初始化,再看下圖:


也就是說繼承BeanNameAware接口的會獲得Bean名稱,繼承BeanFactoryAware接口的會獲得BeanFactory名稱。

3.在App.java中繼承上述兩個接口,並且打印相關信息:

package com.mycompany.app;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

public class App implements InitializingBean,FactoryBean<Object>,BeanNameAware,BeanFactoryAware
{
	private App(){
		System.out.println("App.App()");
	}
	private  String says="App";
    public String getSays() {
		return says;
	}
	public void setSays(String says) {
		this.says = says;
	}
	public void say(){
    	System.out.println("App.app():"+says);
    }
	
	/*如在源碼中看到的,在getset之後,在BeanPostProcessor的after方法之前執行*/
	public void setBeanName(String name) {
		System.out.println("App.setBeanName():"+name);
	}
	/*如在源碼中看到的,在getset之後,在BeanPostProcessor的after方法之前執行*/
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("App.setBeanFactory():"+beanFactory);
	}
	/**
	 * 在構造函數和getset方法之後執行postProcessBeforeInitialization方法
	 */
	/*這個方法是InitializingBean在繼承InitializingBean接口後,要實現的方法,顧名思義,是在
	 *屬性設置之後進行一些操作*/
	public void afterPropertiesSet() throws Exception {
		System.out.println("App.afterPropertiesSet()");
	}
	/*這個方法是在Spring配置中通過init-method屬性指定爲該方法,然後纔會執行,在afterPropertiesSet方法之後*/
	public void initMethod(){
		System.out.println("App.initMethod()");
	}
	/**
	 *在afterPropertiesSet和initMethod方法之後執行postProcessAfterInitialization方法
	 */
	
	/*FactoryBean測試*/
	public Object getObject() throws Exception {
		System.out.println("App.getObject()");
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("test", "GetObject");
		return map;
	}
	@SuppressWarnings("rawtypes")
	public Class<?> getObjectType() {
		return new HashMap().getClass();
	}
	public boolean isSingleton() {
		return true;
	}
}

其他幾個文件前面貼過,這裏再貼上來:

BeanFactoryPostProcessorApp.java

package com.mycompany.app;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class BeanFactoryPostProcessorApp implements BeanFactoryPostProcessor{
	private BeanFactoryPostProcessorApp() {
		System.out.println("BeanFactoryPostProcessorApp.BeanFactoryPostProcessorApp()");
	}

	public void postProcessBeanFactory(
			ConfigurableListableBeanFactory beanFactory) throws BeansException {
		BeanDefinition beanDefinition = (BeanDefinition)beanFactory.getBeanDefinition("app");
		beanDefinition.setAttribute("says", "BeanFactoryPostProcessor");
		System.out
				.println("BeanFactoryPostProcessorApp.postProcessBeanFactory(): "+beanDefinition.getAttribute("says"));
	}

}

BeanPostProcessorApp.java

package com.mycompany.app;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class BeanPostProcessorApp implements BeanPostProcessor{
	
	/*如果打印結果出現該字符串,證明進行了初始化*/
	private BeanPostProcessorApp(){
		System.out.println("BeanPostProcessorApp.BeanPostProcessorApp()");
	}
	
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		if(bean instanceof App){
			((App)bean).setSays("Before:BeanPostProcessorApp");
			System.out
					.println("BeanPostProcessorApp.postProcessBeforeInitialization()");
		}
		return bean;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		if(bean instanceof App){
			((App)bean).setSays("After:BeanPostProcessorApp");
			System.out
					.println("BeanPostProcessorApp.postProcessAfterInitialization()");
		}
		return bean;
	}

}

SpringBean.xml

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">  
   
      
    <bean id="app" class="com.mycompany.app.App" init-method="initMethod"></bean>  
  
  	<bean id="beanPostProcessorApp" class="com.mycompany.app.BeanPostProcessorApp"></bean>
  	
  	<bean id="beanFactoryPostProcessorApp" class="com.mycompany.app.BeanFactoryPostProcessorApp"></bean>
</beans>

BeanFactoryPostProcessorAppTest.java

package com.mycompany.app;

import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanFactoryPostProcessorAppTest {
	public static void main(String[] args) {
    	@SuppressWarnings("resource")
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringBean.xml"); 
        Map map = (Map)applicationContext.getBean("app");  
        System.out.println("BeanFactoryPostProcessorAppTest.main():"+map.get("test").toString());
	}

}

pom.xml

<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>com.mycompany.app</groupId>
  <artifactId>myapp</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>myapp</name>
  <url>http://maven.apache.org</url>
  
  <properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.1.3.RELEASE</spring.version>
  </properties>
  
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
   	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${spring.version}</version>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>${spring.version}</version>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>${spring.version}</version>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context-support</artifactId>
		<version>${spring.version}</version>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>${spring.version}</version>
	</dependency>
  </dependencies>
  
</project>

然後運行BeanFactoryPostProcessorAppTest.java,結果如下:


4.梳理下執行順序:

BeanFactory接口 -> Bean構造函數 -> Bean的GetSet方法 -> Aware接口 -> BeanPostProcessor的Before方法

-> afterPropertiesSet -> initMethod -> BeanPostProcessor的After方法 -> FactoryBean的getObject方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章