跟着课程学一遍,顺便用博客记录下自己的学习历程
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内的某个方法
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相关的具体实现,需要看专业的文献
只有在很复杂的场景里面,综合应用,才能体现你的思考程度和掌握程度