什么Spring IOC
所谓spring 的ioc容器就是将对象通过 getClassLoader 这种方式实例化一个对象放到一个hashMap中,这个 hashMap 就是一个 name 和封装的 bean 对象,而这样每次使用就不用每次都要 new 一个对象,通过 key 就可以直接拿到了。这就是 ioc 的代码主要功能,当然它还有很多好处。所以spring框架的主要思路就是1,解析bean(xml,扫描包,配置文件);2,包装,封装到指定的对象中。
设计模式
设计模式1-模板设计模式
在spring中使用了大量的模板设计模式,父类定义了一个钩子方法(不提供实现具体内容),这样设计可以灵活让子类实现自己的方法,同时通过子类实现钩子方法来干预父类的业务执行流程。
设计模式2-委托模式
有两个对象参与处理同一个请求,接受请求的对象将请求委托给另外一个对象来处理。在spring 中使用得比较多。
设计模式3-装饰模式
步骤一: 扫描并加载bean
spring 加载容器主要有四种方法:
1,通过类路径来加载容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
2,文件系统路径来加载,绝对路径
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("E:\\idea\\public\\springdemo\\src\\main\\resou rces\\spring.xml");
3,无配置文件,包扫描
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.xx.jack");
4,spring boot 加载
ApplicationContext applicationContext = new EmbeddedWebApplicationContext();
spring提供了4种加载bean的方式,其中都是通过实现 AbstractApplicationContext 类中的 refresh() 方法,具体如下:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
.....
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
/**
* 这里主要做了三件事 1,创建BeanFactory对象
* 2,根据上下问不同,统一定义了不同解析bean的过程,没有提供实现
* 3,把解析出来的xml封装成BeanDefinition 对象??
**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//加载beanfactory 所需要的 classloader,已经实现
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(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();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 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();
}
}
}
.....
}
在spring中,提供了BeanDefinition 接口,这个接口始终贯穿了spring 的始终,对于spring 来说实例化bean,只要解析标签,根据不同的方式,例如扫描,xml等把成 BeanDefinition 实例化就可以了。beanDefinition 的实现类有ChildBeanDefinition, GenericBeanDefinition, RootBeanDefinition。
1,ChildBeanDefinition 是可以对RootBeanDefinition 继承的一种bean definition 。它可以继承它父类的设置,对 RootBeanDefinition 有一定的依赖关系。若指定初始化方 法,销毁方法或者静态工厂方法。
2,GenericBeanDefinition 是一站式的标准 bean definition,除了具有指定类、可 选的构造参数值和属性参数这些其它 bean definition 一样的特性外,它还具有通 过 parenetName 属性来灵活设置 parent bean definition。
3,一个 RootBeanDefinition 定义表明它是一个可合并的 bean definition:即在 spring beanFactory 运行期间,可以返回一个特定的 bean。RootBeanDefinition 可 以作为一个重要的通用的 bean definition 视图。
这里通过实现GenericBeanDefinition 在spring容器中注入相关的对象,通过设置实例化自定义beanclass属性来向容器中注入。
MutablePropertyValues 记录的是beanDefinition 的封装标签的信息,通过维护List 这个列表,而PropertyValue 则是一个name-Object 对象。
ConstructorArgumentValues:用于记录封装标签的信息,类里面用于封装构造方法里用到的参数信息。
MethodOverrides:用于封装 lookup-method 和 replaced-method 标签的信息,同样的类里 面有一个 Set 对象添加 LookupOverride 对象和 ReplaceOverride 对象。
总结
这里讲了spring 的一些基础和编码套路。下面文章讲spring 是如何解析bean属性的。