手撸spring源码分析IOC实现原理
文章出处:https://github.com/fuzhengwei/small-spring
根据小付哥的手撸spring核心源码一步步学习出来的结果收货总结。
spring容器Ioc初次体验
BeanDefinition :Object对象。
public class BeanDefinition {
private Object bean;
public BeanDefinition(Object bean) {
this.bean = bean;
}
public Object getBean() {
return bean;
}
}
beanFactory:容器工厂对象。一个map集合用于存储实例对象。
为什么使用map集合进行存储?
ArrayList、LinkedList、HashSet等,但在 Spring Bean 容器的场景下,
我们需要一种可以用于存放和名称索引式的数据结构,所以选择 HashMap 是最合适不过的。
public class BeanFactory {
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
beanDefinitionMap.put(name, beanDefinition);
}
}
public class UserService {
public void queryUserInfo(){
System.out.println("111");
}
public UserService(){
System.out.println("默认无参构造创造");
}
}
@Test
public void test_BeanFactory(){
// 1.初始化 BeanFactory
BeanFactory beanFactory = new BeanFactory();
// 2.注册 bean
BeanDefinition beanDefinition = new BeanDefinition(new UserService());
beanFactory.registerBeanDefinition("userService", beanDefinition);
// 3.获取 bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
}
spring初显身手,运用设计模式,实现 Bean 的定义、注册、获取
本章将 Spring Bean 容器完善起来,首先非常重要的一点是在 Bean 注册的时候只注册一个类信息,而不会直接把实例化信息注册到 Spring 容器中。那么就需要修改 BeanDefinition 中的属性 Object 为 Class,接下来在需要做的就是在获取 Bean 对象时需要处理 Bean 对象的实例化操作以及判断当前单例对象在容器中是否已经缓存起来了
BeanDefinition 定义
public class BeanDefinition {
private Class beanClass;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
// ...get/set
}
单例注册接口定义和实现
//获取单例对象的接口
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<>();
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String name) throws BeansException {
Object bean = getSingleton(name);
if (bean != null) {
return bean;
}
BeanDefinition beanDefinition = getBeanDefinition(name);
return createBean(name, beanDefinition);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean = null;
try {
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) throw new BeansException("No bean named '" + beanName + "' is defined");
return beanDefinition;
}
}
@Test
public void test_BeanFactory(){
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2.注册 bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
// 3.第一次获取 bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
// 4.第二次获取 bean from Singleton
UserService userService_singleton = (UserService) beanFactory.getBean("userService");
userService_singleton.queryUserInfo();
}
执行流程分析
实例化一个容器
需要实例化对象的class,然后注册到容器中
注意:默认调用无参构造进行创建,如果重新了有参构造后会实例失败。
基于Cglib实现含构造函数的类实例化策略
public interface BeanFactory {
Object getBean(String name) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
}
public interface InstantiationStrategy {
Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException;
}
基于jdk的实例化
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
Class clazz = beanDefinition.getBeanClass();
try {
if (null != ctor) {
return clazz.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
} else {
return clazz.getDeclaredConstructor().newInstance();
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new BeansException("Failed to instantiate [" + clazz.getName() + "]", e);
}
}
}
基于Cglib的实例化
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setCallback(new NoOp() {
@Override
public int hashCode() {
return super.hashCode();
}
});
if (null == ctor) return enhancer.create();
return enhancer.create(ctor.getParameterTypes(), args);
}
}
如果实例的:采用cglib
对象属性值填充
从Spring.xml解析和注册Bean对象
优化从配置文件中实例化bean
step1:实例化beanFactory。
step2:
会判断当前传入的location是属于哪些类型的,classpathResource还是fileSystemResource还是Url 判断方式如下图
根据返回的Resource转为输入流,
把当前输入流转为xml对象进行读取属性赋值操作后 放入到DefaultListableBeanFactory中的private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>()中去。此时DefaultListableBeanFactory中的map中已经保存了bean的定义信息,在去进行实例化,从而完成冲配置文件中实例化bean。
step3:如何实例化:
先冲缓存中根据key(bean的name名称)取,如果没有则创建后添加到缓存中并返回,如果有直接返回。
实现应用上下文,自动识别、资源加载、扩展机制
BeanFactoryPostProcessor(bean的定义信息加载之后,bean实例化之前执行改接口实现方法,用于BeanDefinition的修改)
BeanPostProcessor(实例化前的提前处理:准确来说是提前于bean实例化,利用在实例化之前检查是否存在合适的BeanPostProcessor对象,去拦截某些需要被处理的bean提前完成bean的实例化过程,不会去调用init方法,也没有数据的填充)
流程分析图:
准备实体:
public class UserService {
private String uId;
private String company;
private String location;
private UserDao userDao;
//setter and getter
}
MyBeanFactoryPostProcessor:用于测试BeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
PropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.addPropertyValue(new PropertyValue("company", "改为:字节跳动"));
}
}
MyBeanPostProcessor:用于测试BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.setLocation("改为:北京");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
准备就绪开干:
测试方法:
@Test
public void test_xml() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");
// 2. 获取Bean对象调用方法
UserService userService = applicationContext.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
}
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(“classpath:springPostProcessor.xml”)
- 装载所有的Bean对象。
- 具体流程如下图所示
**核心方法:refresh()
refreshBeanFactory();方法(作用: 创建 BeanFactory,并加载 BeanDefinition)
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {
super(registry, resourceLoader);
}
@Override
public void loadBeanDefinitions(Resource resource) throws BeansException {
try {
try (InputStream inputStream = resource.getInputStream()) {
doLoadBeanDefinitions(inputStream);
}
} catch (IOException | ClassNotFoundException e) {
throw new BeansException("IOException parsing XML document from " + resource, e);
}
}
@Override
public void loadBeanDefinitions(Resource... resources) throws BeansException {
for (Resource resource : resources) {
loadBeanDefinitions(resource);
}
}
@Override
public void loadBeanDefinitions(String location) throws BeansException {
ResourceLoader resourceLoader = getResourceLoader();
Resource resource = resourceLoader.getResource(location);
loadBeanDefinitions(resource);
}
@Override
public void loadBeanDefinitions(String... locations) throws BeansException {
for (String location : locations) {
loadBeanDefinitions(location);
}
}
protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {
Document doc = XmlUtil.readXML(inputStream);
Element root = doc.getDocumentElement();
NodeList childNodes = root.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
// 判断元素
if (!(childNodes.item(i) instanceof Element)) continue;
// 判断对象
if (!"bean".equals(childNodes.item(i).getNodeName())) continue;
// 解析标签
Element bean = (Element) childNodes.item(i);
String id = bean.getAttribute("id");
String name = bean.getAttribute("name");
String className = bean.getAttribute("class");
// 获取 Class,方便获取类中的名称
Class<?> clazz = Class.forName(className);
// 优先级 id > name
String beanName = StrUtil.isNotEmpty(id) ? id : name;
if (StrUtil.isEmpty(beanName)) {
beanName = StrUtil.lowerFirst(clazz.getSimpleName());
}
// 定义Bean
BeanDefinition beanDefinition = new BeanDefinition(clazz);
// 读取属性并填充
for (int j = 0; j < bean.getChildNodes().getLength(); j++) {
if (!(bean.getChildNodes().item(j) instanceof Element)) continue;
if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) continue;
// 解析标签:property
Element property = (Element) bean.getChildNodes().item(j);
String attrName = property.getAttribute("name");
String attrValue = property.getAttribute("value");
String attrRef = property.getAttribute("ref");
// 获取属性值:引入对象、值对象
Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;
// 创建属性信息
PropertyValue propertyValue = new PropertyValue(attrName, value);
beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
}
if (getRegistry().containsBeanDefinition(beanName)) {
throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");
}
// 注册 BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);
}
}
}
注册 BeanDefinition: getRegistry().registerBeanDefinition(beanName, beanDefinition);
以上操作完成bean的加载和注册
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
上图只是拿到了banFactory中有哪些是BeanPostProcessor的子类。并不会立即处理。
beanFactory.preInstantiateSingletons(); 实例化对象
到此完成了BeanDefinition的的修改。完成了BeanPostProcessor和BeanFactoryPostProcessor的对bean的不同时机的修改操作!
1.整体流程说明:根据传入的路径。判断出具体的解析方式是classpath,url,FileSystem。然后读取配置中的Bean定义信息。完成对BeanDefinition第一次的初始化操作并放入DefaultListableBeanFactory中的beanDefinitionMap中去。
2.获取到DefaultListableBeanFactory对象。(这个对象包含bean的定义信息)
3.执行BeanFactoryPostProcessor。说白了就拿到实现了BeanFactoryPostProcessor接口的类,然后拿到需要修改的属性。放入List propertyValueList = new ArrayList<>();集合中去。
4,在实例化bean之前提前拿到实现了BeanPostProcessor的类。然后放入AbstractBeanFactory 中的List beanPostProcessors = new ArrayList();集合中去。
5.创建实例:实例化对象(cglib或jdk),给 Bean 填充属性时执行List propertyValueList = new ArrayList<>();循环然后覆盖。执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法。
龙行有风,向虚拟机注册钩子,实现Bean对象的初始化和销毁方法
定义初始化和销毁方法的接口(init-method、destroy-method)加入bean的生命周期
Aware接口作用。
让所有继承Aware接口的接口都具有感知功能。
让所有实现Aware接口的接口的类都能获取对应的属性。
这个在实例化和初始化bean对象之后,bean = initializeBean(beanName, bean, beanDefinition);方法时执行
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);
// 判断 SCOPE_SINGLETON、SCOPE_PROTOTYPE
if (beanDefinition.isSingleton()) {
registerSingleton(beanName, bean);
}
return bean;
}
判断你当前的这个bean对象有没有实现对应的Aware接口,如果实现了,调用对应xxxAware接口的方法,给你塞对应的参数。然后执行一些初始化方法以及前后处理逻辑
// invokeAwareMethods 判断当前bean对象有没有实现各种Aware接口
if (bean instanceof Aware) {
//实现了BeanFactoryAware就调用BeanFactoryAware的setBeanFactory方法。
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. 执行实现了InitializingBean的方法前执行BeanPostProcessor Before 处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 执行 Bean 对象的初始化方法
try {
//2. 执行实现了InitializingBean接口的bean。 invokeInitMethods(beanName, wrappedBean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
}
// 3. 执行实现了InitializingBean的方法后执行执行 BeanPostProcessor After 处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
spring事件处理方法
public void refresh() throws BeansException {
// 6. 初始化事件发布者
initApplicationEventMulticaster();
// 7. 注册事件监听器
registerListeners();
// 9. 发布容器刷新完成事件
finishRefresh();
}
6.1//这个方法就实例化一个SimpleApplicationEventMulticaster对象出来,然后注册进beanFactory工厂中
private void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//这个方法就实例化一个SimpleApplicationEventMulticaster对象出来,然后
applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//注册进beanFactory工厂中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
}
7.1 判断容器内的bean对象,哪些实现了ApplicationListener接口的bean,
全部拿出来,然后放入一个事件监听集合applicationListeners中
private void registerListeners() {
//实现了ApplicationListener接口的bean
Collection<ApplicationListener> applicationListeners = getBeansOfType(ApplicationListener.class).values();
for (ApplicationListener listener : applicationListeners) {
//放入事件监听集合中
applicationEventMulticaster.addApplicationListener(listener);
}
}
// 9.1 比如:发布容器刷新完成事件
//发布的事件对象时ContextRefreshedEvent
publishEvent(new ContextRefreshedEvent(this));
//调用事件发布
public void publishEvent(ApplicationEvent event) {
applicationEventMulticaster.multicastEvent(event);
}
//获取对应的事件监听对象getApplicationListeners(event)方法,然后发布事件
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener listener : getApplicationListeners(event)) {
//发布事件
listener.onApplicationEvent(event);
}
}
//拿到所以的监听事件applicationListeners集合,
//然后判断当前事件和集合中哪些监听事件的类型一致的。supportsEvent(listener, event),就添加到另一个集合中返回出去,然后发布事件
protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) {
LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>();
for (ApplicationListener<ApplicationEvent> listener : applicationListeners) {
if (supportsEvent(listener, event)) allListeners.add(listener);
}
return allListeners;
}
/**
* 监听器是否对该事件感兴趣
*/
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());
}
spring三级缓存解决循环依赖问题(暂未看完)
A 创建时需要依赖 B 创建,而B 的创建又依赖于 A 创建,就这样死循环了
分类:
一级缓存解决方式:
package cn.bugstack.springframework.test;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CircleTest {
private final static Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public static void main(String[] args) throws Exception {
System.out.println(getBean(B.class).getA());
System.out.println(getBean(A.class).getB());
}
private static <T> T getBean(Class<T> beanClass) throws Exception {
String beanName = beanClass.getSimpleName().toLowerCase();
if (singletonObjects.containsKey(beanName)) {
return (T) singletonObjects.get(beanName);
}
// 实例化对象入缓存
Object obj = beanClass.newInstance();
singletonObjects.put(beanName, obj);
// 属性填充补全对象
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Class<?> fieldClass = field.getType();
String fieldBeanName = fieldClass.getSimpleName().toLowerCase();
field.set(obj, singletonObjects.containsKey(fieldBeanName) ? singletonObjects.get(fieldBeanName) : getBean(fieldClass));
field.setAccessible(false);
}
return (T) obj;
}
}
class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
class B {
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
Spring BeanFactory和FactoryBean的区别
BeanFactory | 提供了一系列的获取bean对象的方法。 Object getBean(String name), T getBean(String name, Class requiredType) |
---|---|
FactoryBean | 实现了 FactoryBean 接口的类有能力改变 bean,具有代理作用. |
BeanPostProcessor和BeanFactoryPostProcessor的区别
BeanFactoryPostProcessor | 它的实现类可以在当前BeanFactory初始化(spring容器加载bean定义文件)后,bean实例化之前修改bean的定义属性,达到影响之后实例化bean的效果 |
---|---|
BeanPostProcessor | postProcessBefore Initialization(Object bean, String beanName)和postProcessAfter Initialization(Object bean, String beanName)方法 作用:BeanPostProcessor能在spring容器实例化bean之后,在执行bean的初始化方法前后,修改bean的定义属性,达到影响之后实例化bean的效果 |
ResourceLoader和Resource的区别
Resource | 提供了统一的获取bean的定义方式。xml方式,url方式等 |
---|---|
ResourceLoader | 进一步封装了用于获取Resource的方式。使得用户只需要传入路径,然后判断出是用那种方式获取。 |
ApplicationContext和BeanFactory获取bean的区别
ApplicationContext | ApplicationContext,如果配置的bean是singleton,那么不管你有没有或想不想用它,它都会被实例化(立即加载) |
---|---|
BeanFactory | BeanFactory实例化对象时,配置的bean不会马上被实例化,而是等到你使用该bean的时候(getBean)才会被实例化(懒加载) |
Spring IOC流程分析
创建BeanFactory,并加载BeanDefinition
获取BeanFactory
未完待续-------------------------------