Spring源码解读 IOC篇

跟着课程学一遍,顺便用博客记录下自己的学习历程

IOC容器的使用中,依赖查找和依赖注入是IOC容器的两种实现方式

依赖注入我觉得其实就是Bean的注入吧(对的,通过使用autowired, injected来注入指定的bean),但依赖查找到底是什么,需要后面再探索(依赖查找就是根据bean的名称或者id或者别名,来找到对应的bean,需要jndi等的接口API才能主动获取bean)

ClassPathBeanDefinitionScanner

这个scanner其实就对应<context:component-scan>元素或者ComponentScan注解,会扫描元素中指定的包,这个scanner也被mybatis的ClassPathMapperScanner继承,对应@MapperScan注解

Bean 主要在于生命周期和定义,还有作用域 比如singleton protype request

BeanFactoryPostProcessor

最重要的一个方法是invokeBeanFactoryPostProcessors 最重要的类ConfigureableListableBeanFactory,

1.修改beanDefinition的scope,lazyInit,autowireMode(比如autowire_by_type),dependsOn,beanClass等

2.替换spel表达式,比如${port},PropertySourcesPlaceholderConfigurer是替换${port}的实现类

3. bean默认是手动注入的,可以修改bean的注入方式,比如设置为autowire_by_type,

ignoreDependency,取消bean的自动注入,beanFactory.ignoreDependecyType(B.class);

先通过prorityOrderedPostProcessors.add(beanFactory.getBean())调用方法来实例化,其实实例化就是getBean(),底层调用的newInstance方法,new一个bean,然后通过invokeBeanFactoryPostProcessors,来注入属性之类的

BeanDefinitionRegistryPostProcessor,这个可以通过register,来往beanMap里面注册beanDefinition,所以BeanDefinitionRegistryPostProcessor(以及invokeBeanDefinitionRegistryPostProcessor)一般在BeanFactoryPostProcessor前面 

PropertyDescriptor到底是个啥

为啥spring要用到?PropertyDescriptor.setPropertiesEditor()到底是个啥?PropertiesEditorSupport就是接口的子类,其中实现了接口的大部分或者所有方法

主要是用来把配置文件,比如xml文件中Bean的信息,比如xml里面有个age,是字符串类型,但是java里面对应的bean的age要是Integer类型,这个时候需要用PropertyDescriptor来完成转换

更高级的是PropertiesEditorRegistory

public class SimplePropertyDescriptorTests {

	@Test
	public void toStringOutput() throws IntrospectionException, SecurityException, NoSuchMethodException {
		{
			Object pd = new ExtendedBeanInfo.SimplePropertyDescriptor("foo", null, null);
			assertThat(pd.toString()).contains(
					"PropertyDescriptor[name=foo, propertyType=null, readMethod=null");
		}
		{
			class C {
				@SuppressWarnings("unused")
				public Object setFoo(String foo) { return null; }
			}
			Method m = C.class.getMethod("setFoo", String.class);
			Object pd = new ExtendedBeanInfo.SimplePropertyDescriptor("foo", null, m);
			assertThat(pd.toString()).contains(
					"PropertyDescriptor[name=foo",
					"propertyType=class java.lang.String",
					"readMethod=null, writeMethod=public java.lang.Object");
		}
		

其实只要看看 SimplePropertyDescriptorTests 这个case就知道大概是用来干啥的了,就是为了能够设置属性的 

BeanWrapper和PropertyDescriptor的关系

看看BeanWrapper的接口定义就知道了

	/**
	 * Obtain the PropertyDescriptors for the wrapped object
	 * (as determined by standard JavaBeans introspection).
	 * @return the PropertyDescriptors for the wrapped object
	 */
	PropertyDescriptor[] getPropertyDescriptors();

	/**
	 * Obtain the property descriptor for a specific property
	 * of the wrapped object.
	 * @param propertyName the property to obtain the descriptor for
	 * (may be a nested path, but no indexed/mapped property)
	 * @return the property descriptor for the specified property
	 * @throws InvalidPropertyException if there is no such property
	 */
	PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;

里面有个getPropertyDescriptor,Wrapper其实就是把一个bean包裹起来,然后可以通过getPropertyDescriptor来访问这个Bean的属性,当然我们也可以通过getWrappedInstance获取实际的bean,例子如下:

BeanWrapper company = new BeanWrapperImpl(new Company());
// setting the company name..
company.setPropertyValue("name", "Some Company Inc.");
// ... can also be done like this:
PropertyValue value = new PropertyValue("name", "Some Company Inc.");
company.setPropertyValue(value);

// ok, let's create the director and tie it to the company:
BeanWrapper jim = new BeanWrapperImpl(new Employee());
jim.setPropertyValue("name", "Jim Stravinsky");
company.setPropertyValue("managingDirector", jim.getWrappedInstance());

// retrieving the salary of the managingDirector through the company
Float salary = (Float) company.getPropertyValue("managingDirector.salary");

然后propertyEditor有很多实现,不过我有点怀疑,干嘛要有这么多实现。。

Lifecycle接口,用来管理bean的生命周期

LiveBeansView用来把bean托管到mbeansrver,而mbeanserver 或者jmx,是用来远程或者本地调用(比如通过Jconsole),运行时,jvm内的某个方法

面试官问我 JMX 了解不,我说:什么? - 知乎

AbstractApplicationContext extends DefaultResourceLoader
      implements ConfigurableApplicationContext
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {

 先继承Lifecycle接口,Lifecycle默认实现为DefaultLifecycleProcessor

关闭的步骤

shutdownhook,我的理解,用于优雅关机,比如kill -1到-9

if (this.shutdownHook == null) {
			// No shutdown hook registered yet.
			this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
				@Override
				public void run() {
					synchronized (startupShutdownMonitor) {
						doClose();
					}
				}
			};
			Runtime.getRuntime().addShutdownHook(this.shutdownHook);
		}

运用了回调的机制

spring应用上下文的周期几个阶段?

refresh start stop close

environment的生命周期?

一般在refresh方法中的prepareRefresh方法中

也可以通过setEnviroment来我们手动设置

六大aware接口的回调实现,通过ApplicationContextAwareProcessor来实现(最早的processor?)

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); 

其实是通过类型来注册指定的类对象,类似于getBeanByType

Scope

singleton,是指在BeanFactory里面有唯一一个Bean

request:

其实每次代理对象都是同一个CGLIB代理对象,一直都是User@4336

但是返回给前端的scopeObject(也就是User对象),每个request都是不一样的

有关jsp的el session搜索顺序,如下:

 application不好用,而且容易出问题scopeTarget.user,所以不推荐,会用request和session就不错了

自定义scope

map还有remove(key)操作,自定义基于线程的scope

主要要

1.implement scope覆写getConversationId

2. 还有注册scope

了解spring特性,更需要夯实java api和底层基础,JSR规范

要看得懂英文文档,阅读大量文献,来实操,比如Java并发,不要仅仅了解AQS

JSR相关的具体实现,需要看专业的文献

只有在很复杂的场景里面,综合应用,才能体现你的思考程度和掌握程度

当你看到一个事物的时候你要去怀疑他,然后去解释他,最后得到你想要的答案

惑而不从师其为惑也终不解矣

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值