目的
在大三開始學習spring時,老師就說spring bean周期非常重要,當時也有仔細看,但是說實話搞不大懂,后面工作面試也問過,還是有點模糊,就是沒有掌握好,進行深入理解,這次“老大”又問到了。不允許再回避了,所以這次堅決搞明白,理解生命周期作用,為啥要這樣設計,我們能在生命周期做哪些更高層次的編程。
生命周期流程圖
先總體看下spring的生命周期流程圖,實現(繼承)這些接口(抽象類)並在容器里注冊,就可以看到bean的生命周期會按下面流程進行,后面會給出測試代碼。
可以看出設計策略是“先顧大局”-類似的操作BeanFactory一般出現在Bean之前,操作完Bean之后,BeanFactory會進行“管理”;Bean操作的前提是應用了BeanPostProcessor。
測試代碼
要被注冊的Person類
package springBeanTest; import org.springframework.beans.BeansException; import org.springframework.beans.factory.*; public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean { private String name; private String address; private int phone; private BeanFactory beanFactory; private String beanName; public Person() { System.out.println("【構造器】調用Person的構造器實例化"); } public String getName() { return name; } public void setName(String name) { System.out.println("【注入屬性】name"); this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { System.out.println("【注入屬性】address"); this.address = address; } public int getPhone() { return phone; } public void setPhone(int phone) { System.out.println("【注入屬性】phone"); this.phone = phone; } // 這是BeanFactoryAware接口方法 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("【BeanFactoryAware接口】調用setBeanFactory方法"); this.beanFactory = beanFactory; } // 這是BeanNameAware接口方法 public void setBeanName(String s) { System.out.println("【BeanNameAware接口】調用setBeanName方法"); this.beanName = s; } // 這是DiposibleBean接口方法 public void destroy() throws Exception { System.out.println("【DiposibleBean接口】調用destroy方法"); } // 這是InitializingBean接口方法 public void afterPropertiesSet() throws Exception { System.out.println("【InitializingBean接口】調用afterPropertiesSet方法"); } // 通過<bean>的init-method屬性指定的初始化方法 public void myInit() { System.out.println("【init-method】調用<bean>的init-method屬性指定的初始化方法"); } // 通過<bean>的destroy-method屬性指定的初始化方法 public void myDestory() { System.out.println("【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法"); } }
實現BeanFactoryPostProcessor的類
package springBeanTest; 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 MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{ public MyBeanFactoryPostProcessor() { super(); System.out.println("這是BeanFactoryPostProcessor實現類構造器!!"); } public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { System.out .println("BeanFactoryPostProcessor調用postProcessBeanFactory方法"); BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition("person"); bd.getPropertyValues().addPropertyValue("phone", "110"); } }
繼承InstantiationAwareBeanPostProcessorAdapter的類
package springBeanTest; import java.beans.PropertyDescriptor; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() { super(); System.out .println("這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!"); } // 接口方法、實例化Bean之前調用 @Override public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法"); return null; } // 接口方法、實例化Bean之后調用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法"); return bean; } // 接口方法、設置某個屬性時調用 @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法"); return pvs; } }
實現BeanPostProcessor的類
package springBeanTest; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor{ public MyBeanPostProcessor(){ System.out.println("這是BeanPostProcessor實現類構造器!!"); } public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改"); return o; } public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改"); return o; } }
測試類BeanLifeCycle
package springBeanTest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanLifeCycle { public static void main(String[] args) { System.out.println("現在開始初始化容器"); ApplicationContext factory = new ClassPathXmlApplicationContext("beans.xml"); System.out.println("容器初始化成功"); //得到Preson,並使用 Person person = factory.getBean("person",Person.class); System.out.println(person); System.out.println("現在開始關閉容器!"); ((ClassPathXmlApplicationContext)factory).registerShutdownHook(); } }
配置文件
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor"> </bean> <bean id="instantiationAwareBeanPostProcessor" class="springBeanTest.MyInstantiationAwareBeanPostProcessor"> </bean> <bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor"> </bean> <bean id="person" class="springBeanTest.Person" init-method="myInit" destroy-method="myDestory" scope="singleton" p:name="張三" p:address="廣州" p:phone="123567889"/> </beans>
運行結果如下:
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:57343,suspend=y,server=n -javaagent:C:\Users\shoshana\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;D:\project\myself\demo\springbeanlifedemo\target\classes;D:\dev_env\maven\local_repository\org\springframework\spring-context\4.3.9.RELEASE\spring-context-4.3.9.RELEASE.jar;D:\dev_env\maven\local_repository\org\springframework\spring-aop\4.3.9.RELEASE\spring-aop-4.3.9.RELEASE.jar;D:\dev_env\maven\local_repository\org\springframework\spring-beans\4.3.9.RELEASE\spring-beans-4.3.9.RELEASE.jar;D:\dev_env\maven\local_repository\org\springframework\spring-core\4.3.9.RELEASE\spring-core-4.3.9.RELEASE.jar;D:\dev_env\maven\local_repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\dev_env\maven\local_repository\org\springframework\spring-expression\4.3.9.RELEASE\spring-expression-4.3.9.RELEASE.jar;D:\dev_env\idea\JetBrains\IntelliJ IDEA 2019.1\lib\idea_rt.jar" com.shoshana.service.BeanLifeCycle Connected to the target VM, address: '127.0.0.1:57343', transport: 'socket' 現在開始初始化容器 四月 13, 2019 5:08:17 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17550481: startup date [Sat Apr 13 17:08:17 CST 2019]; root of context hierarchy 四月 13, 2019 5:08:17 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring.xml] 這是BeanFactoryPostProcessor實現類構造器!! BeanFactoryPostProcessor調 用postProcessBeanFactory方法 這是BeanPostProcessor實現類構造器!! 這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!! InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法 InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法 BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改 BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改 InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法 InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法 【構造器】調用Person的構造器實例化 InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法 【注入屬性】phone 【BeanNameAware接口】調用setBeanName方法 【BeanFactoryAware接口】調用setBeanFactory方法 BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改 【InitializingBean接口】調用afterPropertiesSet方法 【init-method】調用<bean>的init-method屬性指定的初始化方法 BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改 InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法 容器初始化成功 com.shoshana.service.Person@38425407 現在開始關閉容器! 四月 13, 2019 5:08:18 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@17550481: startup date [Sat Apr 13 17:08:17 CST 2019]; root of context hierarchy 【DiposibleBean接口】調用destroy方法 【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法 Disconnected from the target VM, address: '127.0.0.1:57343', transport: 'socket' Process finished with exit code 0
生命周期的接口和抽象類
大概了解了生命周期的流程和運用到哪些接口和抽象類之后,下面開始進一步深入了解他們的具體作用,按照流程往下一一介紹。
這里spring版本是4.1.8.RELEASE。
BeanFactoryPostProcessor接口
package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException; }
該接口只有一個postProcessBeanFactory方法,BeanFactoryPostProcessor:在bean factory標准初始化之后可以進行修改。將加載所有bean定義,但是還沒有實例化bean。這個方法允許重新覆蓋或者添加屬性甚至快速的初始化bean。
初次看不知干嘛,關鍵在於參數,可以利用參數做一些操作。
下面了解一下這個參數。
ConfigurableListableBeanFactory 提供分析、修改bean定義和預先實例化單例。這個BeanFactory的子接口不應該是被使用於普通應用程序中:BeanFactory和ListableBeanFactory鐵錚錚作為最經典的用例;這個接口是僅應該允許內部框架使用,即使在訪問bean factory配置方法時也如此。
ConfigurableListableBeanFactory 的方法
- freezeConfiguration():凍結全部bean定義,給被注冊的bean定義發信號告訴它們今后不再被修改和進一步后續處理。它允許factory去積極緩存bean定義元數據。
- getBeanDefinition(String beanName):根據指定的bean name返回被注冊的bean定義,允許訪問其屬性值和構造函數參數值(可以在bean工廠后期處理期間被修改)。這個被返回的bean definition對象不應該是副本而是原始在工廠被注冊的。這意味着如果需要它可以被轉換為更具體的實現類型。注意這個方法只能獲得本地工廠bean definition。
- Iterator getBeanNamesIterator():返回由這個bean factory管理的所有bean name統一視圖。
void ignoreDependencyType(Class<?> type)
:忽略被給定注入依賴類型 ,例如String。void ignoreDependencyInterface(Class<?> ifc)
:忽略被給定注入依賴接口 。這個通常被使用由application contexts去注冊依賴,可以以多種方式實現。例如BeanFactory通過BeanFactoryAware,ApplicationContext 通過ApplicationContextAware。默認情況下,僅BeanFactoryAware接口是被忽略,需要忽略其他接口,調用此方法。boolean isAutowireCandidate(String beanName,DependencyDescriptor descriptor)throws NoSuchBeanDefinitionException
:確認這個被指定的bean是否是一個autowire候選,將被注入到其他聲明匹配類型的依賴的bean中。- isConfigurationFrozen():返回該工廠的bean definnitions是否被凍結。
- preInstantiateSingletons():確保所有非懶加載的單例bean被實例化,包括factoryBeans。
void registerResolvableDependency(Class<?> dependencyType,Object autowiredValue)
:注冊一個特定類型依賴伴隨着相應的autowired值。這個是准備被用於應該可以autowire而不是在這個工廠被定義的bean的工廠/上下文引用。例如 將ApplicationContext類型的依賴項解析為Bean所在的ApplicationContext實例。注意~在普通的BeanFactory中沒有注冊這樣的默認類型,甚至連BeanFactory接口本身都沒有。
postProcessBeanFactory使用示例
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { // TODO: 2018/6/7 覆蓋屬性值 System.out.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法"); BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition("person"); bd.getPropertyValues().addPropertyValue("phone", "110"); // TODO: 2018/6/7 快速初始化bean configurableListableBeanFactory.preInstantiateSingletons(); }
BeanPostProcessor接口
允許自定義修改新bean實例的Factory hook,例如檢查標記接口或者把bean包裝成代理。
ApplicationContext 可以在它們的beans definitions自動檢測BeanPostProcessor bean並且把這些bean應用於隨后的bean創建。普通的bean factory允許對后處理器進行程序化注冊,通過工廠應用於所有bean創建。
BeanPostProcessor 的方法
-
postProcessBeforeInitialization(Object bean, String beanName):在一些bean實例化回調(例如InitializingBean的afterPropertiesSet 或者一個定制的init-method)之前應用這個BeanPostProcessor
-
postProcessAfterInitialization(Object bean, String beanName):在一些bean實例化回調(例如InitializingBean的afterPropertiesSet 或者一個定制的init-method)之后應用這個BeanPostProcessor
BeanPostProcessor用法示例
postProcessBeforeInitialization一
class BeanValidationPostProcessor...
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!this.afterInitialization) { doValidate(bean); } return bean; }
/** * Perform validation of the given bean. * @param bean the bean instance to validate * @see javax.validation.Validator#validate */ protected void doValidate(Object bean) { Set<ConstraintViolation<Object>> result = this.validator.validate(bean); if (!result.isEmpty()) { StringBuilder sb = new StringBuilder("Bean state is invalid: "); for (Iterator<ConstraintViolation<Object>> it = result.iterator(); it.hasNext();) { ConstraintViolation<Object> violation = it.next(); sb.append(violation.getPropertyPath()).append(" - ").append(violation.getMessage()); if (it.hasNext()) { sb.append("; "); } } throw new BeanInitializationException(sb.toString()); } }
檢驗bean狀態是否有效。
postProcessBeforeInitialization二
class ApplicationContextAwareProcessor... public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareInterfaces(bean); return null; } }, acc); } else { invokeAwareInterfaces(bean); } return bean; } private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver( new EmbeddedValueResolver(this.applicationContext.getBeanFactory())); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
判斷bean是什么接口,然后進行set屬性。應該就是api里面說的檢查標記接口。
大概意識是bean已經實例成功,你可以做一些校驗或者補充些內容或者把bean包裝代理注入。包裝代理直接把代理實例返回就行。
postProcessAfterInitialization和postProcessBeforeInitialization類似。
InstantiationAwareBeanPostProcessorAdapter
實現SmartInstantiationAwareBeanPostProcessor全部方法的適配器,這將不改變由容器正常處理每一個實例化的bean。子類僅覆蓋自己想要的方法。
注意,只有在實際需要 InstantiationAwareBeanPostProcessor 功能時,才推薦這個基類。如果您所需要的只是簡單的BeanPostProcessor功能,那么您應該選擇直接實現那個(更簡單的)接口。
-
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
:在實例化目標bean之前應用此BeanPostProcessor。這個返回的bean也許是一個代理代替目標bean,有效地抑制目標bean的默認實例化。如果此方法返回一個非空對象,則bean的創建過程將被短路。唯一的進一步處理被應用是BeanPostProcessor.postProcessAfterInitialization(java.lang.Object, java.lang.String)方法(可以自己試下,改變了bean的生命周期實例化之后直接進入BeanPostProcessor.postProcessAfterInitialization)回調來自於配置好的BeanPostProcessors。這個回調將僅被應用於有bean class的bean defintions。特別是,它不會應用於采用”factory-method“的beans。后處理器可以實現擴展的SmartInstantiationAwareBeanPostProcessor接口,以便預測它們將返回的bean對象的類型。 -
postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
:在工廠將給定的屬性值應用到給定的bean之前,對給定的屬性值進行后處理。允許檢查全部依賴是否已經全部滿足,例如基於一個@Required在bean屬性的setter上。還允許替換要應用的屬性值,通常通過基於原始的PropertyValues創建一個新的MutablePropertyValues實例,添加或刪除特定的值。 -
postProcessAfterInitialization(Object bean, String beanName)
:在bean初始化回調(例如:InitializingBean的afterPropertiesSet或者定制的init-method)之后,應用這個BeanPostProcessor去給一個新的bean實例。bean已經配置了屬性值,返回的bean實例可能已經被包裝。
如果是FactoryBean,這個回調將為FactoryBean實例和其他被FactoryBean創建的對象所調用。這個post-processor可以通過相應的FactoryBean實例去檢查決定是否應用FactoryBean或者被創建的對象或者兩個都有。
這個回調在一個由InstantiationAwareBeanPostProcessor短路的觸發之后將被調用。
看到這里我也沒看懂是啥意思,下面我們看看源代碼。
postProcessBeforeInstantiation使用示例
class AbstractAutoProxyCreator... public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = this.getCacheKey(beanClass, beanName); if(beanName == null || !this.targetSourcedBeans.contains(beanName)) { if(this.advisedBeans.containsKey(cacheKey)) { return null; } if(this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } if(beanName != null) { TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName); if(targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; }
這個可以返回代理。
postProcessPropertyValues使用示例
示例一
class RequiredAnnotationBeanPostProcessor ... @Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { if (!this.validatedBeanNames.contains(beanName)) { if (!shouldSkip(this.beanFactory, beanName)) { List<String> invalidProperties = new ArrayList<String>(); for (PropertyDescriptor pd : pds) { if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) { invalidProperties.add(pd.getName()); } } if (!invalidProperties.isEmpty()) { throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName)); } } this.validatedBeanNames.add(beanName); } return pvs; }
這個方法很明顯校驗需要注入的屬性是否有屬性值。
示例二
@Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { if (bean instanceof EnhancedConfiguration) { ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory); } return pvs; }
在AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法試圖自auto-wire其他配置bean之前注入BeanFactory。
postProcessAfterInitialization使用示例
public Object postProcessAfterInitialization(Object bean, String beanName) { if(bean instanceof AopInfrastructureBean) { return bean; } else { if(bean instanceof Advised) { Advised advised = (Advised)bean; if(!advised.isFrozen() && this.isEligible(AopUtils.getTargetClass(bean))) { if(this.beforeExistingAdvisors) { advised.addAdvisor(0, this.advisor); } else { advised.addAdvisor(this.advisor); } return bean; } } if(this.isEligible(bean, beanName)) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); proxyFactory.setTarget(bean); if(!proxyFactory.isProxyTargetClass()) { this.evaluateProxyInterfaces(bean.getClass(), proxyFactory); } proxyFactory.addAdvisor(this.advisor); return proxyFactory.getProxy(this.getProxyClassLoader()); } else { return bean; } } }
如果bean是一個基礎的aop bean那么就直接返回,如果不是基礎的aop bean並且實現了Advise接口那么就對這個bean進行一些操作,如果不是基礎的aop bean沒實現Advise接口並且是合格的bean就用代理工廠進行代理,如果不是基礎的aop bean沒實現Advise接口並且不是合格的bean那么也直接返回。
總之對已經實例化的bean進行一些處理,可能這個bean在早期已經實例化了又是單例,那么就銷毀這個bean用原來的bean。
BeanNameAware接口
接口是被實現由那些想知道其在bean factory中的名稱的bean實現。請注意,通常不建議對象依賴於它的bean名稱,因為這表示對外部配置的潛在脆弱依賴性,以及對Spring API可能不必要的依賴。
- setBeanName(String name):在創建這個bean的bean factory里設置名字。在填充正常bean屬性之后調用但是在初始化回調之前例如InitializingBean的afterPropertiesSet方法或者一個定制的init-method.
示例
class SchedulerFactoryBean ... public void setBeanName(String name) { if(this.schedulerName == null) { this.schedulerName = name; } }
對工廠bean進行set name
BeanFactoryAware接口
接口由希望知道其擁有的BeanFactory的bean實現。
例如beans可以通過這個工廠去查閱和它合作的beans(查閱依賴)。注意大部分beans將選擇通過協作相應bean屬性或者構造函數參數(依賴注入)去接收協作beans的引用。
- setBeanFactory(BeanFactory beanFactory) :為bean實例提供所屬工廠的回調。在普通的bean屬性值填充之后但是在初始化回調之前(例如InitializingBean的afterPropertiesSet方法或者一個定制的init-method方法)被調用
setBeanFactory示例
public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); if(!(beanFactory instanceof ConfigurableListableBeanFactory)) { throw new IllegalStateException("Cannot use AdvisorAutoProxyCreator without a ConfigurableListableBeanFactory"); } else { this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory); } } protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.advisorRetrievalHelper = new AbstractAdvisorAutoProxyCreator.BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); }
獲得所屬的beanFactory並拷貝到本對象中。可以通過這個bean所屬的beanFactory檢查bean依賴的bean、beanClassLoader、互斥的單例等。
InitializingBean接口
接口被實現由那些需要響應所有已經被BeanFactory set的屬性:例如執行自定義初始化或者僅檢查是否已經set所有必要屬性。
實現InitializingBean的另一種方法是指定一個自定義的init-method,例如在一個XML配置文件中指定bean的init-method。
- afterPropertiesSet():在設置完所有提供的bean屬性(並滿足BeanFactoryAware和ApplicationContextAware)之后由beanFactory調用。這個方法允許bean實例只有在所有的bean屬性都被設置並且在錯誤配置的情況下拋出異常的情況下才能執行初始化。
afterPropertiesSet示例
public void afterPropertiesSet() { if(this.getDataSource() == null) { throw new IllegalArgumentException("Property 'dataSource' is required"); } }
檢查是否已經set所有必要屬性。
/** * Eagerly create the singleton instance, if necessary. */ @Override public void afterPropertiesSet() throws Exception { if (isSingleton()) { this.initialized = true; this.singletonInstance = createInstance(); this.earlySingletonInstance = null; } }
- 這里沒做什么自定義初始化和檢查是否已經set所有必要屬性,而是提前初始化單例bean,說明你可以做一些其他操作。
DisposableBean接口
接口已經被實現由那些想在銷毀釋放資源的bean。如果BeanFactory處理緩存的單例對象,那么它應該調用destroy方法。
應用程序上下文在關閉的時候應該處理它的所有單例。
實現InitializingBean的另一種方法是指定一個自定義的destroy-method,例如在一個XML配置文件中指定bean的destroy-method。
destroy示例
@Override public void destroy() { close(); } /** * Close this application context, destroying all beans in its bean factory. * <p>Delegates to {@code doClose()} for the actual closing procedure. * Also removes a JVM shutdown hook, if registered, as it's not needed anymore. * @see #doClose() * @see #registerShutdownHook() */ @Override public void close() { synchronized (this.startupShutdownMonitor) { doClose(); // If we registered a JVM shutdown hook, we don't need it anymore now: // We've already explicitly closed the context. if (this.shutdownHook != null) { try { Runtime.getRuntime().removeShutdownHook(this.shutdownHook); } catch (IllegalStateException ex) { // ignore - VM is already shutting down } } } } /** * Actually performs context closing: publishes a ContextClosedEvent and * destroys the singletons in the bean factory of this application context. * <p>Called by both {@code close()} and a JVM shutdown hook, if any. * @see org.springframework.context.event.ContextClosedEvent * @see #destroyBeans() * @see #close() * @see #registerShutdownHook() */ protected void doClose() { if (this.active.get() && this.closed.compareAndSet(false, true)) { if (logger.isInfoEnabled()) { logger.info("Closing " + this); } LiveBeansView.unregisterApplicationContext(this); try { // Publish shutdown event. publishEvent(new ContextClosedEvent(this)); } catch (Throwable ex) { logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); } // Stop all Lifecycle beans, to avoid delays during individual destruction. try { getLifecycleProcessor().onClose(); } catch (Throwable ex) { logger.warn("Exception thrown from LifecycleProcessor on context close", ex); } // Destroy all cached singletons in the context's BeanFactory. destroyBeans(); // Close the state of this context itself. closeBeanFactory(); // Let subclasses do some final clean-up if they wish... onClose(); this.active.set(false); } }
執行上下文關閉:發布一個ContextClosedEvent和破壞了這個應用上下文的bean工廠中的單例。