手寫Spring框架-貳
前言
前面已經(jīng)實(shí)現(xiàn)了給類對(duì)象添加了修改注冊(cè)Bean定義未實(shí)例化前的屬性信息修改和初始化過程中的前置和后置處理,
本章實(shí)現(xiàn)Bean的初始化和銷毀方法、Aware感知容器、擴(kuò)展FactoryBean
正文
初始化和銷毀方法
定義初始化和銷毀方法的接口
public interface InitializingBean {
/**
* Bean處理了屬性填充后調(diào)用
* @throws Exception
*/
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
void destroy() throws Exception;
}
定義銷毀方法適配器
@Data
public class DisposableBeanAdapter implements DisposableBean {
private final Object bean;
private final String beanName;
private String destroyMethodName;
public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) {
this.bean = bean;
this.beanName = beanName;
this.destroyMethodName = beanDefinition.getDestroyMethodName();
}
@Override
public void destroy() throws Exception {
// 1. 實(shí)現(xiàn)接口 DisposableBean
if(bean instanceof DisposableBean) {
((DisposableBean) bean).destroy();
}
// 2. 如果 BeanDefinition 配置了 destroy-method,再通過反射調(diào)用
// 但如果同時(shí)實(shí)現(xiàn)了 DisposableBean 且配置的名字剛好就是 "destroy",則跳過,避免重復(fù)調(diào)用
if (StrUtil.isNotEmpty(destroyMethodName)
&& !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))) {
Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
if (null == destroyMethod) {
throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'");
}
destroyMethod.invoke(bean);
}
}
}
在初始化時(shí)調(diào)用初始化方法和注冊(cè)銷毀方法,修改AbstractAutowireCapableBeanFactory抽象類的createBean方法
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
bean = createBeanInstance(beanDefinition, beanName, args);
// 給 Bean 填充屬性
applyPropertyValues(beanName, bean, beanDefinition);
// 執(zhí)行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置處理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 注冊(cè)實(shí)現(xiàn)了 DisposableBean 接口的 Bean 對(duì)象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingleton(beanName, bean);
return bean;
}
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
}
添加虛擬機(jī)關(guān)閉鉤子注冊(cè)調(diào)用銷毀方法
public interface ConfigurableApplicationContext extends ApplicationContext {
void refresh() throws BeansException;
void registerShutdownHook();
void close();
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// ...
@Override
public void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
@Override
public void close() {
getBeanFactory().destroySingletons();
}
}
Aware感知容器
定義Aware接口
標(biāo)記性接口,實(shí)現(xiàn)該接口可以被spring容器感知
public interface Aware {
}
實(shí)現(xiàn)容器感知類
public interface BeanNameAware extends Aware{
void setBeanName(String beanName);
}
public interface BeanFactoryAware extends Aware{
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
public interface BeanClassLoaderAware extends Aware{
void setBeanClassLoader(ClassLoader classLoader);
}
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
由于這些接口需要的東西(BeanName、ClassLoader、BeanFactory)在 BeanFactory 內(nèi)部就能直接拿到,不依賴 ApplicationContext。
而且這幾個(gè)是 基礎(chǔ)級(jí)別 的 Aware 回調(diào),Spring 在最核心的 AbstractAutowireCapableBeanFactory.initializeBean 里就直接處理了,保證所有 Bean 都能拿到這些最底層的元信息。
而這些接口需要的對(duì)象(ApplicationContext、Environment 等)并不是 BeanFactory 自身能提供的,而是只有在 ApplicationContext 級(jí)別才有的上下文信息。
所以,需要專門寫了一個(gè) ApplicationContextAwareProcessor,實(shí)現(xiàn)了 BeanPostProcessor,在 postProcessBeforeInitialization 階段給這些 Bean 注入。
public class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(applicationContext);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
擴(kuò)展FactoryBean
因?yàn)槲覀冊(cè)谑褂?Spring、MyBatis 框架的時(shí)候都可以知道,并沒有手動(dòng)的去創(chuàng)建任何操作數(shù)據(jù)庫的 Bean 對(duì)象,
有的僅僅是一個(gè)接口定義,而這個(gè)接口定義竟然可以被注入到其他需要使用 Dao 的屬性中去了,那么這一過程最核心待解決的問題,
就是需要完成把復(fù)雜且以代理方式動(dòng)態(tài)變化的對(duì)象,注冊(cè)到 Spring 容器中。而為了滿足這樣的一個(gè)擴(kuò)展組件開發(fā)的需求,就需要我們?cè)诂F(xiàn)有手寫的 Spring 框架中,添加這一能力。
定義FactoryBean接口
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
實(shí)現(xiàn)FactoryBean注冊(cè)服務(wù)
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry{
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>();
protected Object getCachedObjectForFactoryBean(String beanName) {
Object object = this.factoryBeanObjectCache.get(beanName);
return (object != NULL_OBJECT ? object : null);
}
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName) {
if(factory.isSingleton()){
Object object = this.getCachedObjectForFactoryBean(beanName);
if(object == null){
object = this.doGetObjectFromFactoryBean(factory, beanName);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}else{
return this.doGetObjectFromFactoryBean(factory, beanName);
}
}
private Object doGetObjectFromFactoryBean(final FactoryBean factory, final String beanName){
try {
return factory.getObject();
} catch (Exception e) {
throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
}
}
}
擴(kuò)展 AbstractBeanFactory 創(chuàng)建對(duì)象邏輯
首先這里把 AbstractBeanFactory 原來繼承的 DefaultSingletonBeanRegistry,修改為繼承 FactoryBeanRegistrySupport。
因?yàn)樾枰獢U(kuò)展出創(chuàng)建 FactoryBean 對(duì)象的能力,所以這就想一個(gè)鏈條服務(wù)上,截出一個(gè)段來處理額外的服務(wù),并把鏈條再鏈接上。
此處新增加的功能主要是在 doGetBean 方法中,添加了調(diào)用 (T) getObjectForBeanInstance(sharedInstance, name) 對(duì)獲取 FactoryBean 的操作。
在 getObjectForBeanInstance 方法中做具體的 instanceof 判斷,另外還會(huì)從 FactoryBean 的緩存中獲取對(duì)象,如果不存在則調(diào)用 FactoryBeanRegistrySupport#getObjectFromFactoryBean,執(zhí)行具體的操作
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, final Object[] args) {
Object sharedInstance = getSingleton(name);
if (sharedInstance != null) {
// 如果是 FactoryBean,則需要調(diào)用 FactoryBean#getObject
return (T) getObjectForBeanInstance(sharedInstance, name);
}
BeanDefinition beanDefinition = getBeanDefinition(name);
Object bean = createBean(name, beanDefinition, args);
return (T) getObjectForBeanInstance(bean, name);
}
private Object getObjectForBeanInstance(Object beanInstance, String beanName) {
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = getCachedObjectForFactoryBean(beanName);
if (object == null) {
FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance;
object = getObjectFromFactoryBean(factoryBean, beanName);
}
return object;
}
// ...
}

浙公網(wǎng)安備 33010602011771號(hào)