Spring技术内幕
第1章 Spring的设计理念和整体架构(略)
第2章 Spring Framework的核心:IoC容器的实现
两个主要容器:
- 实现
接口的简单容器系列:实现容器的最基本功能BeanFactory
-
:增加了许多面向框架的特性,同时对应用环境作了许多适配ApplicationContext
IoC容器的接口设计图:
BeanFactory
接口方法:
-
containsBean
-
isSingleton
-
isPrototype
-
isTypeMatch
-
getType
-
getAliases
设计原理:(以
XmlBeanFactory
为例)
编程式使用IoC容器:
ClassPathResource res = new ClassPathResource("bean.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
步骤:
1. 创建IoC配置文件的抽象资源,这个抽象资源包含了
BeanDefinition
的定义信息
2. 创建一个
BeanFactory
,这里使用
DefaultListableBeanFactory
3. 创建一个载入
BeanDefinition
的读取器,通过一个回调配置给
BeanFactory
4. 从定义好的资源位置读入配置信息,具体的解析过程由
XmlBeanDefinitionReader
来完成。
IoC容器的初始化过程
Resource定位过程:
BeanDefinition的载入和解析:
对IoC容器来说,这个载入过程,相当于把定义的
BeanDefinition
在IoC容器中转化为一个Spring内部表示的数据结构的过程,这些
BeanDefinition
数据在IoC容器中通过一个
HashMap
来保持和维护。
BeanDefinition在IoC容器中的注册:
在
DefaultListableBeanFactory
中实现了
BeanDefinitionRegistry
的接口,这个接口的实现完成
BeanDefinition
向容器的注册,就是把解析得到的
BeanDefinition
设置到
hashMap
中去。
IoC容器的依赖注入
什么时候注入:在用户第一次向IoC容器索要bean的时候(
lazy-init
预实例化除外)
两种实例化Java对象的方法:
- 通过
BeanUtils
,使用Java反射功能
- 通过
CGLIB
的
Enhancer
类的
create
方法
容器初始化和关闭过程
Bean的生命周期:
1. Bean实例的创建
2. 为Bean实例设置属性
3. 调用Bean的初始化方法
4. 应用可以通过IoC容器使用Bean
5. 当容器关闭时,调用Bean的销毁方法
lazy-init属性和预实例化:在
refresh
初始化容器的时候去
getBean
去触发依赖注入
FactoryBean的实现:类似于抽象工厂模式,封装Proxy、RMI、JNDI等
BeanPostProcessor的实现:
两个方法:
postProcessBeforeInitialization
/
postProcessAfterInitialization
IoC容器对Bean的初始化
- 为类型是
BeanNameAware
的Bean设置Bean的名字
- 为类型是
BeanClassLoaderAware
的Bean设置类装载器
- 为类型是
BeanFactoryAware
的Bean设置自身所在的IoC容器以供回调使用
- 对
postProcessBeforeInitialization
/
postProcessAfterInitialization
的回调
- 初始化属性
init-method
的处理
autowiring(自动依赖装配)的实现
//开始进行依赖注入过程,先处理autowiring的注入
if (mbd.getResolvedAutowiredMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowiredMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//这里是对autowire注入的处理,根据Bean的名字或者type进行autowire的过程
if (mbd.getResolvedAutowiredMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (mbd.getResolvedAutowiredMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
第3章 Spring AOP的实现
Spring AOP概述
Advice
通知:
-
BeforeAdvice
:接口
MethodBeforeAdvice
,方法
before()
-
AfterAdvice
:接口
AfterReturningAdvice
,方法
afterReturning()
-
ThrowsAdvice
:在抛出异常时回调,这个回调是AOP通过反射机制完成的。
Pointcut
切点:
概念:决定
Advice
通知应该作用于哪个连接点。返回一个
MethodMatcher
,由它来判断是否需要对当前方法调用进行增强,或者是否需要对当前调用方法应用配置好的
Advice
通知。
- 通过正则表达式进行匹配
- 通过方法名进行匹配
- 等等
Spring AOP的设计和实现
JVM动态代理
Advisor通知器:
概念:将
Advice
和
pointcut
结合起来,可以定义应该使用哪个通知在哪个关注点使用。
建立AopProxy代理对象
ProxyFactoryBean:封装了主要代理对象的生成过程,生成方式有两种
- JDK的Proxy
- CGLIB
JDK生成
AopProxy
代理对象
public Obejct getObject(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class[] proxiedInterfaces AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//这是调用JDK生成Proxy的地方
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
拦截器调用的实现
JdkDynamicAopProxy
的
invoke
拦截:
当Proxy对象的代理方法被调用的时候,
JdkDynamicAopProxy
的
invoke
方法作为Proxy对象的回调函数被触发,从而通过invoke的具体实现,构造
ReflectiveMethodInvocation
对象来完成对目标对象方法调用的拦截或者说功能增强。
Cglib2AopProxy
的
intercept
拦截:
与
JdkDynamicAopProxy
的回调实现非常类似,唯一不同的是构造
CglibMethodInvocation
对象来完成拦截器链的调用。
对目标方法的调用:
- jdk:使用反射机制得到调用方法的反射对象,然后使用invoke启动对方法反射对象的调用。
- cglib:通过
MethodProxy
对象来直接invoke完成的
AOP拦截器链的调用:
1. 先进行判断,如果已经运行到拦截器链的末尾,直接调用目标对象的实现方法
2. 否则,沿着拦截器链继续进行,得到下一个拦截器,通过这个拦截器进行
matches
判断,是否适用于横切增强的场合,如果是,从拦截器中得到通知器,并启动通知器的
invoke
方法进行切面增强
3. 结束之后,迭代调用
proceed
方法,直到拦截器链中的拦截器都完成以上的拦截过程为止
配置通知器:
MethodBeforeAdviceAdapter
的实现
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
MethodBeforeAdviceInterceptor
的实现
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
//为指定的Advice创建对应的MethodBeforeAdviceInterceptor对象
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
//这个invoke方法是拦截器的回调方法,会在代理对象的方法被调用时触发回调
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
AfterReturningAdviceInterceptor
的实现
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
/**
* Create a new AfterReturningAdviceInterceptor for the given advice.
* @param advice the AfterReturningAdvice to wrap
*/
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
Spring AOP的高级特性
HotSwappableTaregetSource
:使用户可以以线程安全的方式切换目标对象,提供所谓的热交换功能。
public synchronized Object swap(Object newTarget) throws IllegalArgumentException {
Assert.notNull(newTarget, "Target object must not be null");
Object old = this.target;
this.target = newTarget;
return old;
}
public synchronized Object getTarget() {
return this.target;
}
第4章 Spring MVC与Web环境
Web环境中的Spring MVC:
SpringMVC是建立在IoC容器基础上的,该容器由
web.xml
里配置的
ContextLoaderListener
负责启动的。
上下文在Web容器的启动:
Spring MVC的设计和实现
DispatcherServlet
的处理过程:
doDispatch
协同模型和控制器的过程:
Handler
的如何获得:
1. 首先会在
HttpRequest
中取得
handler
2. 如果没有,则遍历当前
DispatcherServlet
持有的所有
handlerMapping
,返回需要的
handler
。
Spring MVC视图的呈现
DispathcherServlet
的
render
:
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
// We need to resolve the view name.
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
第5章 数据库操作组件的实现
Spring JDBC
JdbcTemplate
的
execute
实现:
JdbcTemplate
的
query
实现:
Spring JDBC中RDBMS操作对象的实现
SqlQuery
的实现:
SqlUpdate
的实现:
SqlFunction:
Spring驱动Hibernate的设计和实现
基本配置Bean:
LocalSessionFactoryBean
,生成
SessionFactory
,并对Hibernate中的
Session
进行管理
Session的管理:
Spring对Hibernate
Session
的管理功能都是由
SessionFactoryUtils
这个类来提供的。
1. 如果当前线程已绑定事务,
Session
使用的
Connection
是当前线程绑定的那个
2. 新建
Session
和单独使用
SessionFactory
打开新
Session
一样,都是使用
SessionFactory
的
openSession
来创建新的
Session
Spring驱动iBatis的设计与实现
iBatis操作数据库的主要类:
SqlMapClient
,类似于Hibernate的
Session
,是由
SqlMapClientFactoryBean
在依赖注入完成以后被IoC容器回调
afterPropertiesSet
中完成创建的。
第6章 Spring事务处理的实现
Spring声明式事务处理
Spring事务处理的设计与实现
事务的创建:
事务创建的结果是生成一个
TransactionStatus
对象,通过这个对象来保存事务处理需要的基本信息,这个是
TransactionInfo
的一个属性,然后会把
TransactionInfo
保存在
ThreadLocal
对象里,这样当前线程可以通过
ThreadLocal
对象取得
TransactionInfo
以及与这个事务对应的
TransactionStatus
对象,从而把处理信息和调用事务方法的当前线程绑定起来。
Spring事务处理
DataSourceTransactionManager
的实现:
HibernateTransactionManager
的实现:
第7章 Spring远端调用的实现
Spring HTTP调用器的实现
HTTP调用客户端的实现:
HTTP调用器客户端完成远端调用的基本过程:
首先由客户端应用调用代理方法,在调用发生以后,代理类会先运行拦截器,对代理的方法调用进行拦截。在拦截器的拦截行为中,先对本地发生的方法调用进行封装 ,具体来说,就是封装成
MethodInvocation
对象。然后,把这个
MethodInvocation
对象,通过序列化和HTTP请求发送到服务器端,在服务器端的处理完成以后,会通过HTTP响应返回处理结果,这个处理结果被风中在
RemoteInvocationResult
对象中。
HTTP调用服务端的实现:
Spring RMI的实现
Spring RMI客户端的实现:
第8章 安全框架ACEGI的设计与实现
概述
ACGEI验证器的实现
过程:
1. 从
AuthenticationProcessingFilter
拦截HTTP请求开始,接着会从HTTP请求中得到用户输入的用户名和密码,并将这些输入的用户信息放到
Authentication
对象中。
2. 将这个
Authentication
对象传递给
AuthenticationManager
使用,验证器通过持有的
Authentication
对象把它和服务端取得的用户信息进行对比,从而完成用户验证。
3. 验证完成以后,ACEGI会把通过验证的、有效的用户信息封装在一个
Authentication
对象中,供以后的授权器使用
在验证的实现过程中,需要根据ACEGI的要求,配置好各种Provider、UserDetailService以及密码Encoder对象,通过这些对象的协作和功能实现,完成服务器用户数据的获取与用户输入信息的对比和最终的用户验证工作。
ACEGI授权器的实现
过程:
1. 从
FilterSecurityInterceptor
拦截HTTP入手,接着在读取在IoC容器中配置的对URL资源的安全需求以后,会把这些配置信息交由
AccessDecisionManager
授权器进行授权决策
2. 配置好授权器以后,还需要配置一些投票器来完成投票工作,支持授权的决策过程,具体对资源的安全请求进行一个判断
3. 授权器根据授权规则对投票器提交的投票结果进行汇总判断,得到最后的决策结果,从而完成最终的授权工作,最终决定该用户对HTTP请求所要求的URL资源是否有权限获取