Spring ioc容器
IOC容器源码
重要方法 refresh (刷新工程)
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新 准备蛋糕店,基本上就是设置日志,并且new了一个LinkedHashSet
//this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
prepareRefresh();
// 创建一个beanFeactory loadBeanDefinitions(beanFactory)获取蛋糕的制作流程
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
//忽略对应的自动装配
//beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
try {
//spring的扩展 空方法
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
//bean工厂已经基本好了 调用Beanfactory的后置处理器(beanFactory)
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
//初始化方法,就是对bean的依赖进行填充
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//spring的扩张方法
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
实现BeanFactroyPostProcessors接口,这个方法是BeanFactory创建完成后执行的,这是Spring的扩展,用户能添加功能
public class MyBeanFactoryPostProcessors implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
在finishBeanFactoryInitialization(beanFactory);初始化bean之后会执行initializeBean的方法
// 已经完成了创建和属性填充给你的工作
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 1、调用实现的aware接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用beanpostproccessor的BeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用初始化方法在这里 使用xml指定的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用beanpostproccessor的AfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
实现BeanPostProcessors接口 能实现两个方法postProcessBeforeInitialization,postProcessAfterInitialization 分别是初始化之前调用,初始化之后调用,写整个类也是Spring提供的扩展
public class MyBeanPostProcessors implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
手写一个ioc容器
package top.lzy.spring.api.impl;
import top.lzy.clinet.D;
import top.lzy.spring.api.*;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author 卢占勇
* @desc
* @date 2022/3/17
*/
public class ClassPathXmlApplicationContext implements ApplicationContext {
private ConcurrentHashMap<String,Object> beanFactory;
private ConcurrentHashMap<String, BeanFactroyPostProcessor> beanFactroyPostProcessor = new ConcurrentHashMap<>(64);
private ConcurrentHashMap<String,BeanPostProcessor> beanPostProcessor = new ConcurrentHashMap<>(64);
private Properties beanDefinitions = new Properties();
public ClassPathXmlApplicationContext(String config) {
InputStream inputStream = readXML(config);
try {
//将propertise文件直接加载为类
beanDefinitions.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
refresh();
}
private void refresh() {
//1、准备环境
prepareRefresh();
//2、创建店面
beanFactory = new ConcurrentHashMap(64);
//3、准备Beanfactory 忽略一些东西
prepareBeanFactory(beanFactory);
try {
//4 、 客户可以重写该方法 后置处理容器,例如:再添加一个bean
postProcessBeanFactory(beanFactory);
// 调用beanFactory后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessors
registerBeanPostProcessors(beanFactory);
//完成实例化bean,并注入依赖
finishBeanFactoryInitialization(beanFactory);
}catch (Exception e){
e.printStackTrace();
}
}
private void registerBeanPostProcessors(ConcurrentHashMap<String, Object> beanFactory) {
//拿到所以的bean的后置处理器,然后注册
beanPostProcessor.put("D",new D());
}
private void invokeBeanFactoryPostProcessors(ConcurrentHashMap<String, Object> beanFactory) {
//找到beanFactory的后置处理器 然后调用它的方法
//一般用来修改bean的定义 现在beanFactory还没有bean 因为没有初始化
for (Map.Entry<String,BeanFactroyPostProcessor> entry:beanFactroyPostProcessor.entrySet()){
BeanFactroyPostProcessor bfpp = entry.getValue();
bfpp.postProcessBeanFactory(beanFactory);
}
}
private void finishBeanFactoryInitialization(ConcurrentHashMap<String, Object> beanFactory) {
//1、创建
for (Map.Entry<Object,Object> entry:beanDefinitions.entrySet()) {
String className = (String) entry.getValue();
Constructor beanContructor = null;
Object bean =null;
try {
beanContructor = Class.forName(className).getConstructor();
bean = beanContructor.newInstance();
beanFactory.put((String) entry.getKey(), bean);
} catch (NoSuchMethodException | ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
//2、依赖注入
//4、初始化前 beforeBeanPostProcessor
for (Map.Entry<String,BeanPostProcessor> entry1:beanPostProcessor.entrySet()){
entry1.getValue().postProcessBeforeInitialization(bean,(String) entry.getKey());
}
//调用aware
if (bean instanceof ApplicationContextAware){
ApplicationContextAware applicationContextAware = (ApplicationContextAware) bean;
applicationContextAware.setApplicationContextAware(this);
}
//5、初始化
if (bean instanceof Init){
Init init = (Init) bean;
init.init();
}
//6、初始化化后 afterBeanPostProcessor
for (Map.Entry<String,BeanPostProcessor> entry1:beanPostProcessor.entrySet()){
entry1.getValue().postProcessAfterInitialization(bean,(String) entry.getKey());
}
beanFactory.put((String) entry.getKey(),entry.getValue());
}
}
private void postProcessBeanFactory(ConcurrentHashMap<String, Object> beanFactory) {
System.out.println("正在解析注解");
beanFactroyPostProcessor.put("bf",new ConfigBeanFactoryPostProcessor());
}
private void prepareBeanFactory(ConcurrentHashMap<String, Object> beanFactory) {
}
private void prepareRefresh() {
System.out.println("准备刷新,基本上就是设置日志,并且new了一个LinkedHashSet, 看适不适合蛋糕店");
}
@Override
public Object getBean(String name) {
return beanFactory.get(name);
}
@Override
public InputStream readXML(String config) {
return Thread.currentThread().getContextClassLoader().getResourceAsStream(config);
}
}
手写一个ioc容器梳理过程
梳理ClassPathXmlApplicationComtext一下流程
1、在构造器中去读取配置文件,将配置文件加载为一个类,然后进入核心方法刷新
2、先准备刷新工作,该过程就是设置一下日志,(就是看看合不合适创建蛋糕店)
3、创建一个店面,基本理解为一个容器吧(整个过程其实很复杂,手写的简化了)
4、准备beanFactory,就是忽略一些东西,例如忽略对应的自动装配
5、进入try(我认为这个时候进入try就是因为下面就有客户能扩展的一些方法)
6、后置处理beanFactory(postProcessBeanFactory),这是一个空方法,客户端能够重写该方法,能够添加一些bean,解析注解等
7、调用beanfactory后置处理器,找到beanFactory后置处理器,然后调用它的方法postProcessBeanFactory
8、注册bean后置处理器,拿到所以bean的后置处理器然后注册到该类的成员属性map中
9、开始进入初始化bean的方法
1、创建,通过全限定名拿到class对象,拿到构造器,实例化
2、通过类对象拿到成员变量注入依赖
3、使用bean的后置处理器,调用初始化前的处理器方法
4、查看该对象是否实现ApplicationAware,实现set方法
5、调用初始化方法,就那个xml注册的初始化方法init-method
6、使用bean的后置处理器,调用初始化后的处理器方法