上一篇博文中已经介绍过怎么去编译Spring framework源码了,其实很简单,无非就是下载依赖然后构建工具会自动build项目。
- 编译 Spring framework 5.2.17源码 & 在源码中使用 ApplicationContext 获取定义的Bean
使用过Spring系列框架进行开发的朋友应该都知道Bean,它是Spring IOC(控制反转)或者说DI(依赖注入)的基本单位,Spring通过BeanFactory来管理Bean,使得我们不需要手动去实例化这些被依赖Bean,而是由Spring的BeanFactory去发现Bean之间的依赖关系,从而实现Autowired(自动注入);当然实现这些功能还是有点复杂的,从源码中也可以看出,这里只是简单的概述;看源码不能急躁,一步一步去探索,最后发现没有尽头(ㄒoㄒ)。
比如AbstractBeanFactory中的doGetBean方法中有实现Bean之间的依赖关系。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 保证对当前bean所依赖的bean进行初始化。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// beanName和dep之间存在循环依赖关系
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
上面只是为了引出Bean以及BeanFactory的一些概念,实际上要复杂的多,博主也会在以后的博客中进行详细介绍。
很显然BeanFactory能够感知到Bean的存在(ApplicationContext(应用上下文)的实现类通过一些工具类来解析注解定义、类路径信息以及XML配置文件等Bean定义源来感知Bean,如AnnotationConfigApplicationContext中的AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner以及XmlWebApplicationContext中的XmlBeanDefinitionReader等),并且创建和管理这些Bean。
而Bean怎么感知到BeanFactory的存在呢?,我们定义一个Bean一般就直接加注解或者在XML配置文件中进行定义,但这些定义不会涉及到BeanFactory的信息,BeanFactory就像是一个黑盒子;那现在就有一个问题了,当我们定义的Bean需要BeanFactory的一些信息该怎么办呢?这就是Aware接口及其实现类干的事情了,而aware也有意识到的意思,也就是意识到BeanFactory某些信息的存在。
package org.springframework.beans.factory;
public interface Aware {}
英文的大概意思:
- 一个起标记作用的超接口,指示Bean可以通过回调形式的方法得到特定框架对象的Spring容器的通知。实际的方法由各个子接口决定(根据需要),但通常只包含一个接受单个参数并且返回void的方法。
- 仅仅实现Aware接口并不会提供默认功能。相反,处理必须显式地完成,例如在BeanPostProcessor接口中。参考ApplicationContextAwareProcessor中处理特定Aware接口回调的例子。
不需要深究BeanPostProcessor是什么,只需要知道在Bean调用初始化方法的前后会调用BeanPostProcessor中的方法,对Bean实现定制化的功能。
ApplicationContextAwareProcessor中的postProcessBeforeInitialization方法就是在Bean调用初始化方法的之前会被调用,该方法又会调用invokeAwareInterfaces方法,在该方法中就会调用Aware接口实现类中的接受单个参数并且返回void的方法。
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction
EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware以及ApplicationContextAware都是Aware接口的子接口。
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
所以,在Bean调用初始化方法的前后,会有一些方法去调用Aware接口实现类中的方法,从而实现通过回调形式的方法得到特定框架对象的Spring容器的通知,这样Bean就可以获取到BeanFactory的一些信息了。
当然,还有一些Aware接口的子接口,比如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware、ServletContextAware以及ServletConfigAware等,其实这些子接口,在Bean的整个生命周期中有所体现,以便让Bean感知BeanFactory的各种信息,实现特定的功能。而这些子接口的回调是在其他类中实现的,AbstractAutowireCapableBeanFactory抽象类和ServletContextAwareProcessor类中。
AbstractAutowireCapableBeanFactory抽象类(继承了AbstractBeanFactory抽象类):
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
ServletContextAwareProcessor类(实现了BeanPostProcessor接口):
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (getServletContext() != null && bean instanceof ServletContextAware) {
((ServletContextAware) bean).setServletContext(getServletContext());
}
if (getServletConfig() != null && bean instanceof ServletConfigAware) {
((ServletConfigAware) bean).setServletConfig(getServletConfig());
}
return bean;
}
到这里大家应该知道Aware接口及其实现类的作用了吧,其中的方法会在创建Bean的过程中被回调,设置一些BeanFactory中的信息。
在Spring framework 源码中创建一个子Module,在上一篇博客中已经介绍过了,这里就不赘述了。
IMessageService接口:
package com.kaven.service;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContextAware;
public interface IMessageService extends ApplicationContextAware, BeanFactoryAware {
String getMessage();
}
实现类MessageServiceImpl:
package com.kaven.service.impl;
import com.kaven.service.IMessageService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
@Service("message")
public class MessageServiceImpl implements IMessageService {
@Override
public String getMessage() {
return "Hello Kaven";
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("----------------MessageServiceImpl----------------------");
System.out.println("setApplicationContext");
System.out.println(applicationContext.getBeanDefinitionCount());
System.out.println(applicationContext);
System.out.println("----------------MessageServiceImpl----------------------");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("----------------MessageServiceImpl----------------------");
System.out.println("setBeanFactory");
System.out.println(beanFactory);
System.out.println("----------------MessageServiceImpl----------------------");
}
}
启动类Application:
package com.kaven;
import com.kaven.service.IMessageService;
import com.kaven.service.impl.MessageServiceImpl;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
import java.util.Arrays;
@ComponentScan({"com.kaven"})
public class Application implements BeanNameAware, EnvironmentAware {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
IMessageService service = (MessageServiceImpl) context.getBean("message");
System.out.println(service.getMessage());
System.out.println(context.getBeanDefinitionCount());
Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);
((Application)context.getBean("application")).print("Hello Kaven");
}
public void print(String str){
System.out.println(str);
}
@Override
public void setBeanName(String name) {
System.out.println("---------Application----------");
System.out.println(name);
System.out.println("---------Application----------");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("---------Application----------");
System.out.println(environment);
System.out.println("---------Application----------");
}
}
输出结果:
显然是可以的。
阅读源码需要耐心,一步一步进行Debug,每个人的理解不同,如果博主有说错的地方,欢迎大家指正。



