我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring菜鸟教你看源码冲面试

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring菜鸟教你看源码冲面试

Spring

类的初始化和实例化的不同

在这里插入图片描述

IOC

探究spring的IOC容器

DefaultListableBeanFactory是最终实现类,在代码中可以找到HashMap的影子;IOC容器就是用HashMap装的Bean;


public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Nullable
	private static Class<?> javaxInjectProviderClass;

	static {
		try {
			javaxInjectProviderClass =
					ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - Provider interface simply not supported then.
			javaxInjectProviderClass = null;
		}
	}


	
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<>(8);

	
	@Nullable
	private String serializationId;

	
	private boolean allowBeanDefinitionOverriding = true;

	
	private boolean allowEagerClassLoading = true;

	
	@Nullable
	private Comparator<Object> dependencyComparator;

	
	private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;

	
	private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

	
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	
	private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);

	
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

	
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

	
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

	
	private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

	
	@Nullable
	private volatile String[] frozenBeanDefinitionNames;
................
...........
}

BeanFactory:主要方法为getBean(String beanName),该方法根据Bean名称从容器返回对应的Bean

BeanFactory是接口,提供了IOC容器最基本的形式,给具体的IOC容器的实现提供了规范,

在这里插入图片描述

发现BeanFactory是Spring的IOC容器核心接口,它的职责包括,实例化,有很多的实现类;

在这里插入图片描述

原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等

在这里插入图片描述

那么BeanFactroy是否有AOP的影子呢?

找到BeanFactroyAware接口看到很多关键字有proxy类似代理的接口

so 猜想是否跟AOP(面向切面,动态代理)有关

在这里插入图片描述

然后点进去其中一个方法(AbstractAutoProxyCreator),发现引入很多跟AOP相关的包


import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.ProxyProcessorSupport;
import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
import org.springframework.aop.target.SingletonTargetSource;

往下看看这个类,做了什么?找几个方法出来;

看看类的注释

此类区分通用拦截器(由创建的所有代理共享)和特定拦截器:每个bean实例唯一。不需要任何通用拦截器。如果存在,则使用interceptorNames属性设置它们。
与{@link org.springframework.aop.framework.ProxyFactoryBean}一样,使用当前工厂中的拦截器名称而不是bean引用来正确处理原型顾问程序和拦截器例如,以支持有状态的混合。{@link #set InterceptorNames interceptorNames}条目支持任何建议类型。 如果有大量的豆需要用类似的代理包装,即委托给相同的拦截器,则这种自动代理特别有用。 代替x个目标bean的x个重复代理定义,您可以在bean工厂注册一个这样的后处理器,以达到相同的效果


public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport 
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
  
	public void setInterceptorNames(String... interceptorNames) {
		this.interceptorNames = interceptorNames;
	}

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);
    
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);
		proxyFactory.setFrozen(this.freezeProxy);
    
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
		return proxyFactory.getProxy(getProxyClassLoader());
	}
  
  
}

AbstractAutoProxyCreator类关系UML图

在这里插入图片描述

说明AOP横切在Bean的生命周期中


AOP

Spring 通过 AbstractAutoProxyCreator 来创建 AOP 代理,AbstractAutoProxyCreator 是一个抽象类,它实现了 BeanPostProcessor 接口,用于在 bean 初始化完成之后创建它的代理(从上面IOC容器创建Bean过程中有点体现);

在AbstractAutoProxyCreator类关系UML图中找到一个特殊的接口—>BeanPostProcessor

划重点:

  • 与工厂挂钩,允许自定义修改新bean实例,如检查标记接口或使用代理包装bean
  • 普通的{@code BeanFactory}允许以编程方式注册后处理器,并将其应用于通过bean工厂创建的所有bean中;跟上面的AOP横切BeanFactroy联系上了;


public interface BeanPostProcessor {

	
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

在来看这张图(IOC容器工作过程) BeanPostProcessor就是AOP切入的位置,处在对象的生命周期中;

在这里插入图片描述 

BeanFactoryPostProcessor(初始化Bean,如上图)


public interface BeanFactoryPostProcessor {
	
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

另外提点东西(来自面试) BeanFactory 简介以及它 和FactoryBean的区别(阿里面试)

FactoryBean接口是什么?

看看官方注释:

在BeanFactory中的对象实现的接口,这些对象本身是个单个对象的工厂,如果这些对象实现FactoryBean接口,它将用作对象公开的工厂,而不是直接将自身公开;

在这里插入图片描述

好像还是有点蒙吧看看其他解释

FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
FactoryBean接口用的是Class<?> getObjectType();可以理解为高级定制Bean;

看FactoryBean接口抽象类(AbstractFactoryBean)


public abstract class AbstractFactoryBean<T>
		implements FactoryBean<T>, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
	
	protected final Log logger = LogFactory.getLog(getClass());
	private boolean singleton = true;
	@Nullable
	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
	@Nullable
	private BeanFactory beanFactory;
	private boolean initialized = false;
	@Nullable
	private T singletonInstance;
	@Nullable
	private T earlySingletonInstance;

	
	public void setSingleton(boolean singleton) {
		this.singleton = singleton;
	}
	@Override
	public boolean isSingleton() {
		return this.singleton;
	}
	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		this.beanClassLoader = classLoader;
	}
	@Override
	public void setBeanFactory(@Nullable BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}
	
	@Nullable
	protected BeanFactory getBeanFactory() {
		return this.beanFactory;
	}

	
	protected TypeConverter getBeanTypeConverter() {
		BeanFactory beanFactory = getBeanFactory();
		if (beanFactory instanceof ConfigurableBeanFactory) {
			return ((ConfigurableBeanFactory) beanFactory).getTypeConverter();
		}
		else {
			return new SimpleTypeConverter();
		}
	}
  
	@Nullable
	private T getSingletonInstance() throws IllegalStateException {
		Assert.state(this.initialized, "Singleton instance not initialized yet");
		return this.singletonInstance;
	}
}

看完FactoryBean接口抽象类(AbstractFactoryBean)基本的代码后,发现什么?

FactoryBean基于BeanFactory,FactoryBean是一个能生产或者修饰对象生成的工厂Bean;

FactoryBean中定义了一个Spring Bean的很重要的三个特性:是否单例、Bean类型、Bean实例

ApplicationContext接口,

由BeanFactory接口派生而来

看到ApplicationContext接口

提供应用程序配置的中央接口。在应用程序运行时为只读,但如果实现支持,则可以重新加载。
ApplicationContext提供:

  • 用于访问应用程序组件的Bean工厂方法。继承自{@link org.springframework.beans.factory.ListableBeanFactory}。
  • 以通用方式加载文件资源的能力。继承自{@link org.springframework.core.io.ResourceLoader}接口。
  • 将事件发布到注册的侦听器的能力。继承自{@link ApplicationEventPublisher}接口。
  • 解决消息的能力,支持国际化。继承自{@link MessageSource}接口。
  • 从父上下文继承。在后代上下文中的定义将始终优先。例如,这意味着整个Web应用程序都可以使用单个父上下文,而每个servlet都有自己的子上下文,而该子上下文独立于任何其他servlet的子上下文。
  • 除了标准的{@link org.springframework.beans.factory.BeanFactory}生命周期功能之外,ApplicationContext实现还检测并调用{@link ApplicationContextAware} Bean以及{@link ResourceLoaderAware },{@link ApplicationEventPublisherAware}和{@link MessageSourceAware} bean。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

	
	@Nullable
	String getId();

	
	String getApplicationName();

	
	String getDisplayName();

	
	long getStartupDate();

	
	@Nullable
	ApplicationContext getParent();

	
	AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

ApplicationContext接口UML类图

在这里插入图片描述

ApplicationContext有两个主要的实现类:ClassPathXmlApplicationContext:默认从类路径加载配置文件,还有FileSystemXmlApplicationContext:默认从文件系统中装载配置文件

WebApplicationContext

提供Web应用程序配置的界面。在应用程序运行时为只读,但是如果实现支持,则可以重新加载。此接口在通用ApplicationContext接口中添加了一个{@code getServletContext()}方法,并定义了一个众所周知的应用程序属性名称,该名称必须在引导过程中绑定到根上下文。类似于通用应用程序上下文,Web应用程序上下文是分层的。 每个应用程序只有一个根上下文,而应用程序中的每个servlet(包括MVC框架中的调度程序servlet)都有自己的子上下文。除了标准的应用程序上下文生命周期功能外,WebApplicationContext实现还需要检测{@link ServletContextAware} bean,并相应地调用{@code setServletContext}方法


public interface WebApplicationContext extends ApplicationContext {

	
	String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

	
	String SCOPE_REQUEST = "request";

	
	String SCOPE_SESSION = "session";

	
	String SCOPE_APPLICATION = "application";

	
	String SERVLET_CONTEXT_BEAN_NAME = "servletContext";

	
	String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";

	
	String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";


	
	@Nullable
	ServletContext getServletContext();
}

WebApplicationContext的UML类图(从图中可以发现WebApplicationContext扩展了ApplicationContext的功能,ApplicationContext扩展了BeanFactory的功能。)

在这里插入图片描述

这几个接口间的区别

BeanFactory和ApplicationContext, WebApplicationContext初始化区别:BeanFactory在初始化容器时并没有实例化Bean,而是在第一次访问到目标Bean时才实例化该Bean;而ApplicationContext会在初始化上下文时实例化所有的单例的Bean。WebApplicationContext的初始化需要servletContext实例(getServletContext();),即初始化需要拥有web容器,我们需要在web.xml中配置自启动的servlet或web容器监听器(servletContextListener)

Bean的作用域

在BeanFactory和ApplicationContext中的Bean的作用域有两种:
singleton和prototype,
在WebApplicationContext中的Bean的作用域有三种:request,session和globalSession。
singleton:在IOC容器中仅存在一个Bean实例,Bean以单例方式存在,外部引用都指向这个Bean
prototype:每次调用Bean都返回一个新实例
request:在同一个Http请求的Bean相同,每个Http请求创建一个新的Bean。
session:在Http请求对应同一个session时对应同一个Bean。
globalSession:一般的web应用中globalSession等价于session,只有在portlet web应用中才存在globalSession概念。

到此这篇关于Spring菜鸟教你看源码冲面试的文章就介绍到这了,更多相关Spring源码内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring菜鸟教你看源码冲面试

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录