先说初始化方法:
@Override protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException { Object bean = null; try { // 前面的操作 // 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法 !!! bean = initializeBean(beanName, bean, beanDefinition); } catch (Exception e) { throw new BeansException("Instantiation of bean failed", e); } // 注册实现了 DisposableBean 接口的 Bean 对象 !!! 这里需要保存起来哪些Bean是含有销毁时方法的,在最后需要执行 registerDisposableBeanIfNecessary(beanName, bean, beanDefinition); registerSingleton(beanName, bean); return bean; }
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) { // 1. 执行 BeanPostProcessor Before 处理 Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 执行 Bean 对象的初始化方法, try { // 本次的核心 !!! invokeInitMethods(beanName, wrappedBean, beanDefinition); } catch (Exception e) { throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e); } // 2. 执行 BeanPostProcessor After 处理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); return wrappedBean; }
初始化方法调用
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception { // 1. 实现接口 InitializingBean if (bean instanceof InitializingBean) { ((InitializingBean) bean).afterPropertiesSet(); } // 2. 注解配置 init-method {判断是为了避免二次执行初始化} String initMethodName = beanDefinition.getInitMethodName(); if (StrUtil.isNotEmpty(initMethodName) && !(bean instanceof InitializingBean)) { Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName); if (null == initMethod) { throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'"); } initMethod.invoke(bean); } }
注册含有Destroy方法的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)); } }
那现在初始化方法已经执行完了,Destroy方法什么时候执行? 这里我们用到了JVM的钩子函数,我们先定义接口
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(); } }
将DisposableBean封装为DisposableBeanAdapter,未来调用
public class DisposableBeanAdapter implements DisposableBean { @Override public void destroy() throws Exception { // 1. 实现接口 DisposableBean if (bean instanceof DisposableBean) { ((DisposableBean) bean).destroy(); } // 2. 注解配置 destroy-method {判断是为了避免二次执行销毁} 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); } } }
Close() 时具体的操作
public void close() { getBeanFactory().destroySingletons(); } public void destroySingletons() { Set<String> keySet = this.disposableBeans.keySet(); Object[] disposableBeanNames = keySet.toArray(); for (int i = disposableBeanNames.length - 1; i >= 0; i--) { Object beanName = disposableBeanNames[i]; // 从单例工厂中删除 DisposableBean disposableBean = disposableBeans.remove(beanName); try { // 调用的是DisposableBeanAdapter重载的Destroy,最终调用Bean自身定义的Destroy。 disposableBean.destroy(); } catch (Exception e) { throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e); } } }
第八章:感知容器对象
需求:在Bean初始化时,能够感知到容器对象,通过容器对象进行一系列操作
定义Aware接口,表示是可感知的对象,具体由子类实现
@Override public void refresh() throws BeansException { // 1. 创建 BeanFactory,并加载 BeanDefinition // 2. 获取 BeanFactory // 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext !!! beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); // 4. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor // 5. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作 // 6. 提前实例化单例Bean对象 }
这里的第三步,因为无法在Bean初始化时感知到ApplicationContext属性,所以将ApplicationContext写入一个BeanPostProcessor,这样在执行初始化前就可以获取并分配ApplicationContext了。
AbstractAutowireCapableBeanFactory:createBean()调用
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) { // invokeAwareMethods 这里就是将所有内容进行注入的地方 if (bean instanceof Aware) { if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(this); } if (bean instanceof BeanClassLoaderAware){ ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } } }
总之当Bean实现Aware实现类后,当Bean被注入属性后,就会将对应的容器对象进行填充,得到一个完整的对象。
第九章:对象作用域与FactoryBean
FactoryBean 和 BeanFactory有什么区别?
BeanFactory是用来获取Bean的,FactoryBean它本身是一个Bean,但它本身也是一个工厂,可以内部通过动态代理,凝聚出一个功能更完善的Bean,未来这个获取Bean获取的就是FactoryBean内部代理的Bean,可对原本的方法做出调整,而不需要修改原先基本的代码。
为什么需要FactoryBean?
可以扩充自己的对象功能了。MyBatis 就是实现了一个 MapperFactoryBean 类,在 getObject 方法中提供 SqlSession 对执行 CRUD 方法的操作
如何使用FactoryBean?
定义一个类实现FactoryBean接口,实现内部的getObject(),然后注册到容器中即可。
AbstractBeanFactory::doGetBean
protected <T> T doGetBean(final String name, final Object[] args) { Object sharedInstance = getSingleton(name); if (null != sharedInstance) { // 如果是 FactoryBean,则需要调用 FactoryBean#getObject,获取FactoryBean中定义的元素 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) { // 判断是否为FactoryBean,如果不是则直接返回 if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } // 缓存中找 Object object = getCachedObjectForFactoryBean(beanName); if (object == null) { FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance; // !!! 获取或创建FactoryBean内对象 object = getObjectFromFactoryBean(factoryBean, beanName); } return object; }
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName) { if (factory.isSingleton()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = doGetObjectFromFactoryBean(factory, beanName); this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT)); } return (object != NULL_OBJECT ? object : null); } else { return doGetObjectFromFactoryBean(factory, beanName); } }
第十章:容器事件与事件监听器
这里将用到观察者模式,比如说我们有一个注册用户的业务,注册业务成功后,需要发送短信通知,我们最初就是将注册代码与发送短信代码写在了一起,后来自己定义观察者与被观察者,实际上Spring为了更好的扩容性和灵活性,加入了事件监听机制,我们下面来自己设计如何控制事件:
定义和实现事件
事件广播器: 可用于添加,删除监听,广播事件,通过对应的监听器进行通知
事件监听器,自定义监听器,执行自定义事件触发方法
事件如何发送?并触发对应的事件相应方法?
@Test public void test_event() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml"); // 发送事件 applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功了!")); applicationContext.registerShutdownHook(); }
@Override public void publishEvent(ApplicationEvent event) { // 通过事件广播器进行通知 applicationEventMulticaster.multicastEvent(event); }
@Override public void multicastEvent(final ApplicationEvent event) { // 找到事件对应的监听器,并执行方法 for (final ApplicationListener listener : getApplicationListeners(event)) { listener.onApplicationEvent(event); } }
/** * 监听器是否对该事件感兴趣 */ protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) { Class<? extends ApplicationListener> listenerClass = applicationListener.getClass(); // 按照 CglibSubclassingInstantiationStrategy、SimpleInstantiationStrategy 不同的实例化类型,需要判断后获取目标 class Class<?> targetClass = ClassUtils.isCglibProxyClass(listenerClass) ? listenerClass.getSuperclass() : listenerClass; Type genericInterface = targetClass.getGenericInterfaces()[0]; Type actualTypeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0]; String className = actualTypeArgument.getTypeName(); Class<?> eventClassName; try { eventClassName = Class.forName(className); } catch (ClassNotFoundException e) { throw new BeansException("wrong event class name: " + className); } // 判定此 eventClassName 对象所表示的类或接口与指定的 event.getClass() 参数所表示的类或接口是否相同,或是否是其超类或超接口。 // isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。 return eventClassName.isAssignableFrom(event.getClass()); }