文章目录
- 目标
- 设计思想
- 项目结构
- 一、实现
- 1、定义标记接口
- 2、容器感知类
- 2.1、BeanFactoryAware
- 2.2、BeanFactoryAware
- 2.3、BeanNameAware
- 2.4、ApplicationContextAware
- 3、包装处理器(ApplicationContextAwareProcessor)
- 4、注册 BeanPostProcessor
- 5、感知调用操作
- 二、测试
- 1、事先准备
- 2、配置文件
- 3、单元测试
- 总结
目标
本章目标实现获得Spring 框架提供的 BeanFactory、ApplicationContext、BeanClassLoader、ApplicationContextAware等这些能力.,并且还知道他们都是什么时候触发的,在以后想排查类的实例化顺序也可以有一个清晰的思路了。
在 Spring 框架中提供一种能感知容器操作的接口,如果谁实现了这样的一个接口,就可以获取接口入参中的各类能力
设计思想
如果说我希望拿到 Spring 框架中一些提供的资源,那么首先需要考虑以一个什么方式去获取,之后你定义出来的获取方式,在 Spring 框架中该怎么去承接,实现了这两项内容,就可以扩展出你需要的一些属于 Spring 框架本身的能力了。
在关于 Bean 对象实例化阶段我们操作过一些额外定义、属性、初始化和销毁的操作,其实我们如果像获取 Spring 一些如 BeanFactory、ApplicationContext 时,也可以通过此类方式进行实现。
那么我们需要定义一个标记性的接口,这个接口不需要有方法,它只起到标记作用就可以,而具体的功能由继承此接口的其他功能性接口定义具体方法,最终这个接口就可以通过 instanceof 进行判断和调用了。整体设计结构如下图
项目结构
一、实现
1、定义标记接口
/**
* 标记类接口,实现该接口可以被Spring容器感知
*/
public interface Aware {
}
在 Spring 中有特别多类似这样的标记接口的设计方式,它们的存在就像是一种标签一样,可以方便统一摘取出属于此类接口的实现类,通常会有 instanceof 一起判断使用。
2、容器感知类
2.1、BeanFactoryAware
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
实现此接口,就能感知到所属的 BeanFactory
2.2、BeanFactoryAware
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
实现此接口,既能感知到所属的 ClassLoader
2.3、BeanNameAware
public interface BeanNameAware extends Aware{
void setBeanName(String name);
}
实现此接口,既能感知到所属的 BeanName
2.4、ApplicationContextAware
public interface ApplicationContextAware extends Aware{
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
实现此接口,既能感知到所属的 ApplicationContext
3、包装处理器(ApplicationContextAwareProcessor)
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;
}
}
由于 ApplicationContext 的获取并不能直接在创建 Bean 时候就可以拿到,所以需要在 refresh 操作时,把 ApplicationContext 写入到一个包装的 BeanPostProcessor 中去,再由 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization 方法调用
4、注册 BeanPostProcessor
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException {
// 1. 创建 BeanFactory,并加载 BeanDefinition
refreshBeanFactory();
// 2. 获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
invokeBeanFactoryPostProcessors(beanFactory);
// 5. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
registerBeanPostProcessors(beanFactory);
// 6. 提前实例化单例Bean对象
beanFactory.preInstantiateSingletons();
}
// ...
}
refresh() 方法就是整个 Spring 容器的操作过程,与上一章节对比,本次新增加了关于 addBeanPostProcessor 的操作。
添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext。
5、感知调用操作
因为这个类代码太多,这里只展示展示本章相关类的代码,
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);
// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 注册实现了 DisposableBean 接口的 Bean 对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingleton(beanName, bean);
return bean;
}
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);
}
}
// 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(bean, beanName);
return wrappedBean;
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
}
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {
/**
* ClassLoader to resolve bean class names with, if necessary
*/
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
//...
public ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
}
1、在AbstractAutowireCapableBeanFactory 的initializeBean (初始化方法)中添加判断,通过判断 bean instanceof Aware,调用了三个接口方法,BeanFactoryAware.setBeanFactory(this)、BeanClassLoaderAware.setBeanClassLoader(getBeanClassLoader())、BeanNameAware.setBeanName(beanName),这样就能通知到已经实现了此接口的类。
2、在AbstractBeanFactory抽象类中添加beanClassLoader和提供get方法,
3、另外我们还向 BeanPostProcessor 中添加了 ApplicationContextAwareProcessor,此时在这个方法中也会被调用到具体的类实现,得到一个 ApplicationContex 属性
二、测试
1、事先准备
public class UserDao {
private static Map<String, String> hashMap = new HashMap<>();
public void initDataMethod(){
System.out.println("UserDao xml的实现, 执行:init-method");
hashMap.put("10001", "ljc");
hashMap.put("10002", "yaya");
hashMap.put("10003", "zz");
}
public void destroyDataMethod(){
System.out.println("UserDao xml的实现, 执行:destroy-method");
hashMap.clear();
}
public String queryUserName(String uId) {
return hashMap.get(uId);
}
}
public class UserService implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware {
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
private String uId;
private String company;
private String location;
private UserDao userDao;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println("Bean Name is:" + name);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("ClassLoader:" + classLoader);
}
// ...get/set
}
UserDao 本次并没有什么改变,还是提供了关于初始化的方法,并在 Spring.xml 中提供 init-method、destroy-method 配置信息。
UserService 新增加,BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware,四个感知的实现类,并在类中实现相应的接口方法
2、配置文件
基础配置,无BeanFactoryPostProcessor、BeanPostProcessor,实现类
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="springframework.test.bean.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>
<bean id="userService" class="springframework.test.bean.UserService">
<property name="uId" value="10001"/>
<property name="company" value="腾讯"/>
<property name="location" value="深圳"/>
<property name="userDao" ref="userDao"/>
</bean>
</beans>
本章节中并没有额外新增加配置信息,与上一章节内容相同。
3、单元测试
@Test
public void test_xml() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
// 2. 获取Bean对象调用方法
UserService userService = applicationContext.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
System.out.println("ApplicationContextAware:"+userService.getApplicationContext());
System.out.println("BeanFactoryAware:"+userService.getBeanFactory());
测试方法中主要是添加了一写关于新增 Aware 实现的调用,其他不需要调用的也打印了相应的日志信息,可以在测试结果中看到。
UserDao xml的实现, 执行:init-method
ClassLoader:sun.misc.Launcher$AppClassLoader@14dad5dc
Bean Name is:userService
测试结果:ljc, 公司:腾讯, 地点深圳
ApplicationContextAware:cn.ljc.springframework.context.support.ClassPathXmlApplicationContext@153f5a29
BeanFactoryAware:cn.ljc.springframework.beans.factory.support.DefaultListableBeanFactory@7f560810
UserDao xml的实现, 执行:destroy-method
Process finished with exit code 0
从测试结果可以看到,本章节新增加的感知接口对应的具体实现(BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware),已经可以如期输出结果了。
总结
目前关于 Spring 框架的实现中,某些功能点已经越来趋向于完整,尤其是 Bean 对象的生命周期,已经有了很多的体现,结构如下图