并发Map使用场景
Spring框架
核心组件(Bean组件,Context组件,Core组件)
Spring注解
它的强大之处:预处理。
注解实际上相当于一种标记,它允许你在运行时(源码、文档、类文件我们就不讨论了)动态地对拥有该标记的成员进行操作。
实现注解需要三个条件(我们讨论的是类似于Spring自动装配的高级应用):注解声明、使用注解的元素、操作使用注解元素的代码。
Spring IOC与AOP
Spring的一切都是反射
IoC容器的初始化包括BeanDefinition的Resouce定位、载入和注册这三个基本的过程
BeanDefinition的载入可以说是IoC容器的核心
AOP实现中,可以看到三个主要的步骤,一个是代理对象的生成,然后是拦截器的作用,然后是Aspect编织的实现。
代理模式有三个角色分别是通用接口、代理、真实对象。代理、真实对象实现的是同一接口,将真实对象作为代理的一个属性,向客户端公开的是代理,当客户端调用代理的方法时,代理找到真实对象,调用真实对象方法,在调用之前之后提供相关的服务,如事务、安全、日志。其名词分别是代理、真实对象、装备、关切点、连接点。
代理的两种方式:
静态代理:
针对每个具体类分别编写代理类; 针对一个接口编写一个代理类;
动态代理:
针对一个方面编写一个InvoctionHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类
动态代理原理
下面我们来分析一下上述代码的关键所在。
首先来看一下这段代码:
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
java.lang.reflect.Proxy.newProxyInstance方法根据传入的接口类型 (obj.getClass.getInterfaces())动态构造一个代理类实例返回,这也说明了为什么动态代理实现要求其所代理的对象一定要实现 一个接口。这个代理类实例在内存中是动态构造的,它实现了传入的接口列表中所包含的所有接口。
再来分析以下代码:

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
……
result = method.invoke(originalObject, args);
……
return result;
}

InvocationHandler.invoke方法将在被代理类的方法被调用之前触发。通过这个方法,我们可以在被代理类方法调用的前后进行一些处 理,如代码中所示,InvocationHandler.invoke方法的参数中传递了当前被调用的方法(Method),以及被调用方法的参数。同 时,可以通过method.invoke方法调用被代理类的原始方法实现。这样就可以在被代理类的方法调用前后写入任何想要进行的操作
Spring JDBC
spring事务管理机制
Spring的事务管理机制实现的原理,就是通过这样一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的 方法名进行判定,并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。Spring中的AOP实 现更为复杂和灵活,不过基本原理是一致的。
spring Bean的生命周期
spring的生命周期为:实例化前奏-->实例化-->实例化后期-->初始化前期-->初始化-->初始化后期-->bean的具体调用-->销毁前-->销毁。
spring Bean调用的三种实现方式
BeanWrapper
BeanFactory
ApplicationContext
Context构成部件
下图是web application context的类图,可以和构成部件的结构图结合着看,上面的图每个实体都是spring context的一个接口。
常见的WebApplicationContext实现主要有两个,分别是XmlWebApplicationContext和AnnotationConfigWebApplicationContext。他们共同的父类为AbstractRefreshableWebApplicationContext
spring中ApplicationContext加载机制。
加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet。
AbstractApplicationContext源码解析加载过程:
1 public void refresh() throws BeansException, IllegalStateException {
2 synchronized (this.startupShutdownMonitor) {
3 // Prepare this context for refreshing.
4 prepareRefresh();
5
6 // Tell the subclass to refresh the internal bean factory.
7 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
8
9 // Prepare the bean factory for use in this context.
10 prepareBeanFactory(beanFactory);
11
12 try {
13 // Allows post-processing of the bean factory in context subclasses.
14 postProcessBeanFactory(beanFactory);
15
16 // Invoke factory processors registered as beans in the context.
17 invokeBeanFactoryPostProcessors(beanFactory);
18
19 // Register bean processors that intercept bean creation.
20 registerBeanPostProcessors(beanFactory);
21
22 // Initialize message source for this context.
23 initMessageSource();
24
25 // Initialize event multicaster for this context.
26 initApplicationEventMulticaster();
27
28 // Initialize other special beans in specific context subclasses.
29 onRefresh();
30
31 // Check for listener beans and register them.
32 registerListeners();
33
34 // Instantiate all remaining (non-lazy-init) singletons.
35 finishBeanFactoryInitialization(beanFactory);
36
37 // Last step: publish corresponding event.
38 finishRefresh();
39 }
40
41 catch (BeansException ex) {
42 // Destroy already created singletons to avoid dangling resources.
43 destroyBeans();
44
45 // Reset 'active' flag.
46 cancelRefresh(ex);
47
48 // Propagate exception to caller.
49 throw ex;
50 }
51 }
52 }
public void refresh() throws BeansException, IllegalStateException {
2 synchronized (this.startupShutdownMonitor) {
3 // Prepare this context for refreshing.
4 prepareRefresh();
5
6 // Tell the subclass to refresh the internal bean factory.
7 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
8
9 // Prepare the bean factory for use in this context.
10 prepareBeanFactory(beanFactory);
11
12 try {
13 // Allows post-processing of the bean factory in context subclasses.
14 postProcessBeanFactory(beanFactory);
15
16 // Invoke factory processors registered as beans in the context.
17 invokeBeanFactoryPostProcessors(beanFactory);
18
19 // Register bean processors that intercept bean creation.
20 registerBeanPostProcessors(beanFactory);
21
22 // Initialize message source for this context.
23 initMessageSource();
24
25 // Initialize event multicaster for this context.
26 initApplicationEventMulticaster();
27
28 // Initialize other special beans in specific context subclasses.
29 onRefresh();
30
31 // Check for listener beans and register them.
32 registerListeners();
33
34 // Instantiate all remaining (non-lazy-init) singletons.
35 finishBeanFactoryInitialization(beanFactory);
36
37 // Last step: publish corresponding event.
38 finishRefresh();
39 }
40
41 catch (BeansException ex) {
42 // Destroy already created singletons to avoid dangling resources.
43 destroyBeans();
44
45 // Reset 'active' flag.
46 cancelRefresh(ex);
47
48 // Propagate exception to caller.
49 throw ex;
50 }
51 }
52 }
大概讲一下这refresh()里面都干了些什么,这些步骤实际上就是实例化之前的一系列美丽动作:
第9行:准备bean factory (BeanFactory是spring框架的基础设施)
第16行:调用被注册为bean的BeanFactoryPostProcessors(工厂后处理器) (工厂后处理器负责对实例化之前未成形的bean进行加工处理)
第19行:注册BeanPostProcessors(Bean后处理器)来阻挡bean的创建。 (实例化后的bean需要用这个后处理器来进一步加工)
第22行:初始化消息源(国际化信息资源)。 (国际化很容易理解吧?比如微信可以切换中英文版本等等,后面会独列篇幅讲解)
第25行:初始化应用上下文事件广播器。 (spring有一套完善的事件发布和监听机制,事件广播器负责把事件通知给监听器,监听器来执行事件。后面会独列篇幅讲解)。
第28行:初始化其他特殊的bean。
第31行:检查是否有监听器然后注册监听器(监听器就跟bean一样,需要放在注册表中。后面会独列篇幅讲解)。
第34行:初始化所有单实例的bean(懒模式bean除外),单实例的bean初始化后把bean的引用放在spring容器的缓存中,调用者使用的是同一个额引用,任何一个调用者对bean的修改都会影响其他调用者。懒模式是指,spring容器启动时不会初始化,而在需要用到该bean时才初始化。
第37行:创建上下文刷新事件,发布广播器。 (事件机制后面会独列篇幅讲解)
上面这些就是bean实例化前后的细枝末节了。
细化一下创建一个完整的bean的作业流程:
具体点:
- ResourceLoader加载XML配置信息后,由BeanDefinitionReader读取配置信息文件,把每个<bean>解析成BeanDefinition对象保存在BeanDefinitionRegistry注册表中。这时的BeanDefinition可能只是个半成品,因为某些XML属性配置里会有占位符变量,这些变量此时不会被解析出来,需要继续优化,比如下面这样:
1 <bean id="simpleBean" class="com.spring.ch04.SimplePostProcessor"> 2 <property name="connectionString" value="${simpleBean.connectionString}"/> 3 <property name="password" value="${simpleBean.password}"/> 4 <property name="username" value="${simpleBean.username}"/> 5 6 </bean>
<bean id="simpleBean" class="com.spring.ch04.SimplePostProcessor"> 2 <property name="connectionString" value="${simpleBean.connectionString}"/> 3 <property name="password" value="${simpleBean.password}"/> 4 <property name="username" value="${simpleBean.username}"/> 5 6 </bean> - 因为有1的情况出现,所以容器首先扫描注册表取出工厂后处理器,对注册表中的BeanDefinition进行加工处理,把占位符替换成真正的值,产生成品的BeanDefinition。
- 通过反射机制扫描BeanDefinitionRegistry所有属性编辑器的bean类,并把这些bean放到spring容器的属性编辑器注册表(PropertyEditorRegistry)中。(Spring的属性编辑器负责将配置文件中的文本配置值转换为Bean属性的配置值,这个后面会独辟章节来讲)。
- Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy着手对bean的实例化工作。(这里的实例化只是相当于new了一个新对象一样,也就是说,只是跑一个构造函数,不会具体的为属性设置值,当然如果构造函数里写了设置值的语句,那么也可以赋值。比如一开始的那个例子,实例化时在构造函数里就给Car的name属性附上了"宝马"的名字)。
- 实例化的过程中,spring容器使用BeanWrapper对bean进行封装,BeanWrapper结合BeanDefinition和属性编辑器注册表中的属性编辑器完成bean的属性设置工作。
- 最后调用Bean后处理器对bean 作最后的润色。
Spring Web
Spring RMI
Spring ACEGI框架