Bean生命周期
BeanFactory这个类的注释上写了Bean生命周期中执行的方法顺序
- 解析类得到
BeanDefinition - 使用
BeanFactoryPostProcessor对BeanDefinition进行增强,如把${}占位符换成具体的值 - 创建对象,填充属性
- 回调Aware方法,比如
BeanNameAware,BeanFactoryAware - 调用
BeanPostProcessorbefore() - 调用
InitializingBean.afterPropertiesSet() - 调用
BeanPostProcessorafter()(此处进行AOP) - 把Bean放入map中
- 容器关闭时调用
DisposableBean中destory()方法
Bean创建过程中的方法
getBean()doGetBean()getSingleton()createBean()doCreateBean()createBeanInstance()populateBean()initializeBean()
AOP切面
生成一个bean对象的代理对象,对原来的bean进行前置增强,后置增强等,并将代理对象放入容器中,spring使用的是jdk代理,springboot是cglib代理
循环依赖处理过程
- Spring首先把创建bean对象的工厂放入三级缓存
- 当发生循环依赖时,会先从三级缓存中拿到创建该bean对象的bean工厂,然后生成bean的代理对象,并放入二级缓存中,进行提前暴露
- 最后所有的bean初始化完会放入一级缓存
三级缓存
- 三级缓存:存储创建bean的工厂对象(函数式接口)
- 二级缓存:存储已经创建但未完全初始化的对象,避免循环依赖
- 一级缓存:存储完全初始化的对象
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
Aware接口的作用
Aware接口用来获取容器中的某些对象。在Bean初始化过程中,会调用Aware接口的实现方法,spring会将相应的参数传入进去,如beanName、applicationContext、environment,可以借此拿到相应对象,当事务发生内部回调时,可以通过拿到容器对象来避免事务不执行
@Data
@Service
public class UserService implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
public void test() {
UserService userService = (UserService) context.getBean("userService");
System.out.println("ok");
}
}
源码:AbstractAutowireCapableBeanFactory
private void invokeAwareMethods(final String beanName, final 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);
}
}
}
FactoryBean的作用
这个接口里面有一个T getObject()方法,从容器中取对象的时候,最后实际得到的对象是getObject方法返回的结果。可以用来创建复杂的对象,比如通过加载配置文件才能实例化对象
public class UserService implements FactoryBean<Object> {
public Object getObject() throws Exception {
return new Date();
}
public Class<?> getObjectType() {
return Date.class;
}
}
BeanFactoryPostProcessor和BeanPostProcessor区别
-
BeanPostProcessor:处理Bean属性,在InitializingBean初始化对象前后进行处理,如进行AOP生成代理对象AbstractAdvisorAutoProxyCreator -
BeanFactoryPostProcessor:处理BeanDefinition属性,如处理占位符PlaceholderConfigurerSupportpublic class DkBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //获取coder的BeanDefinition对象 BeanDefinition coder = beanFactory.getBeanDefinition("coder"); //修改其class coder.setBeanClassName(Manager.class.getName()); } }
涉及的设计模式
- 单例模式 : Spring 中的 Bean 默认都是单例的
- 代理模式 : Spring AOP 功能的实现
- 责任链模式:SpringMvc中的拦截器,多个拦截器串联起来就形成了责任链
SpringBoot中的starter
在starter中会定义相应的AutoConfiguration,如RedisAutoConfiguration,MybatisAutoConfiguration,在这些configuration中就定义了要用到的第三方Bean对象,然后在 starter包的META-INF/spring.factories中写入该配置类,SpringBoot的自动配置机制加载这个配置类,完成自动配置
SpringMVC工作流程

-
用户发送请求到
DispatcherServlet -
执行拦截器的前置处理方法
preHandle(),如果返回false,请求处理中止 -
DispatcherServlet通过HandlerMapping找到能够处理这个请求的Handler(比如处理静态资源的ResourceHttpRequestHandler,HandlerMethod) -
执行控制器中的业务逻辑
-
执行后置拦截器
postHandle() -
如果返回的是视图,进行视图解析和渲染,如果返回的是对象,将对象转换成json
-
视图渲染或json解析完后,调用拦截器的
afterCompletion()方法 -
响应客户端
过滤器和拦截器的区别
-
过滤器是servlet包中提供的接口,拦截器是springmvc中提供的
-
过滤器执行的时间更早
-
拦截器中可以访问控制器中返回的数据模型,过滤器不可以
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){ if(modelAndView != null) { Object message = modelAndView.getModel().get("message"); Object user = modelAndView.getModel().get("user"); } }

