一:IOC容器创建和注入依赖,通过反射。
二.IOC容器在web应用中的启动流程
先了解web应用在tomcat中的启动流程
spring mvc只需在应用启动的过程中执行初始化操作,创建好容器并通过spring ioc根据配置文件创建好对象
1.在web.xml中配置ContextLoaderListener事件监听器
- //这里对根上下文进行初始化。
- public void contextInitialized(ServletContextEvent event) {
- //这里创建需要的ContextLoader
- this.contextLoader = createContextLoader();
- //这里使用ContextLoader对根上下文进行载入和初始化
- this.contextLoader.initWebApplicationContext(event.getServletContext());
- }
2.完成对ContextLoaderListener的初始化以后, Tomcat开始初始化DispatchServlet,在servlet生命周期中的init阶段,新建一个ApplicationContext并以根上下文为父,注册到ServletCintext中.初始化后:
- protected void initFrameworkServlet() throws ServletException, BeansException {
- initMultipartResolver();
- initLocaleResolver();
- initThemeResolver();
- initHandlerMappings();
- initHandlerAdapters();
- initHandlerExceptionResolvers();
- initRequestToViewNameTranslator();
- initViewResolvers();
- }
完成springmvc各个元素的建立
三:spring mvc框架的实现:
DispatcherServlet工作流程:
以springmvc中DispatchServlet中的init方法入手,以initHandlerMappings()举例
- private void initHandlerMappings() throws BeansException {
- if (this.detectAllHandlerMappings) {
- // 这里找到所有在上下文中定义的HandlerMapping,同时把他们排序
- // 因为在同一个上下文中可以有不止一个handlerMapping,所以我们把他们都载入到一个链里进行维护和管理
- Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
- getWebApplicationContext(), HandlerMapping.class, true, false);
- if (!matchingBeans.isEmpty()) {
- this.handlerMappings = new ArrayList(matchingBeans.values());
- // 这里通过order属性来对handlerMapping来在list中排序
- Collections.sort(this.handlerMappings, new OrderComparator());
- }
- }
- else {
- try {
- Object hm = getWebApplicationContext().getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
- this.handlerMappings = Collections.singletonList(hm);
- }
- catch (NoSuchBeanDefinitionException ex) {
- // Ignore, we'll add a default HandlerMapping later.
- }
- }
- //如果在上下文中没有定义的话,那么我们使用默认的BeanNameUrlHandlerMapping
- if (this.handlerMappings == null) {
- this.handlerMappings = getDefaultStrategies(HandlerMapping.class);
- ........
- }
- }
- public interface HandlerMapping {
- public static final String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE =
- Conventions.getQualifiedAttributeName(HandlerMapping.class, "pathWithinHandlerMapping");
- //实际上维护一个HandlerExecutionChain,这是典型的Command的模式的使用,这个执行链里面维护handler和拦截器
- HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
- }
- public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
- //这里根据request中的参数得到其对应的handler,具体处理在AbstractUrlHandlerMapping中
- Object handler = getHandlerInternal(request);
- //如果找不到对应的,就使用缺省的handler
- if (handler == null) {
- handler = this.defaultHandler;
- }
- //如果缺省的也没有,那就没办法了
- if (handler == null) {
- return null;
- }
- // 如果handler不是一个具体的handler,那我们还要到上下文中取
- if (handler instanceof String) {
- String handlerName = (String) handler;
- handler = getApplicationContext().getBean(handlerName);
- }
- //生成一个HandlerExecutionChain,其中放了我们匹配上的handler和定义好的拦截器,就像我们在HandlerExecutionChain中看到的那样,它持有一个handler和一个拦截器组。
- return new HandlerExecutionChain(handler, this.adaptedInterceptors);
- }
- protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
- //这里的HTTP Request传进来的参数进行分析,得到具体的路径信息。
- String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
- .......//下面是根据请求信息的查找
- return lookupHandler(lookupPath, request);
- }
- protected Object lookupHandler(String urlPath, HttpServletRequest request) {
- // 如果能够直接能在SimpleUrlHandlerMapping的映射表中找到,那最好。
- Object handler = this.handlerMap.get(urlPath);
- if (handler == null) {
- // 这里使用模式来对map中的所有handler进行匹配,调用了Jre中的Matcher类来完成匹配处理。
- String bestPathMatch = null;
- for (Iterator it = this.handlerMap.keySet().iterator(); it.hasNext();) {
- String registeredPath = (String) it.next();
- if (this.pathMatcher.match(registeredPath, urlPath) &&
- (bestPathMatch == null || bestPathMatch.length() <= registeredPath.length())) {
- //这里根据匹配路径找到最象的一个
- handler = this.handlerMap.get(registeredPath);
- bestPathMatch = registeredPath;
- }
- }
- if (handler != null) {
- exposePathWithinMapping(this.pathMatcher.extractPathWithinPattern(bestPathMatch, urlPath), request);
- }
- }
- else {
- exposePathWithinMapping(urlPath, request);
- }
- //
- return handler;
- }
- public class HandlerExecutionChain {
- private Object handler;
- private HandlerInterceptor[] interceptors;
- ........
- }
整个spring mvc的请求会被DispatchServlet拦截,进行分发,由doService调用doDispatch
- protected void doDispatch(final HttpServletRequest request, HttpServletResponse response) throws Exception {
- HttpServletRequest processedRequest = request;
- //这是从handlerMapping中得到的执行链
- HandlerExecutionChain mappedHandler = null;
- int interceptorIndex = -1;
- ........
- try {
- //我们熟悉的ModelAndView开始出现了。
- ModelAndView mv = null;
- try {
- processedRequest = checkMultipart(request);
- // 这是我们得到handler的过程
- mappedHandler = getHandler(processedRequest, false);
- if (mappedHandler == null || mappedHandler.getHandler() == null) {
- noHandlerFound(processedRequest, response);
- return;
- }
- // 这里取出执行链中的Interceptor进行前处理
- if (mappedHandler.getInterceptors() != null) {
- for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {
- HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
- if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
- triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
- return;
- }
- interceptorIndex = i;
- }
- }
- //在执行handler之前,用HandlerAdapter先检查一下handler的合法性:是不是按Spring的要求编写的。
- HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
- // 这里取出执行链中的Interceptor进行后处理
- if (mappedHandler.getInterceptors() != null) {
- for (int i = mappedHandler.getInterceptors().length - 1; i >= 0; i--) {
- HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
- interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
- }
- }
- }
- ........
- // Did the handler return a view to render?
- //这里对视图生成进行处理
- if (mv != null && !mv.wasCleared()) {
- render(mv, processedRequest, response);
- }
- .......
- }
配置到handler的映射关系和怎样根据请求参数得到对应的handler,在Spring中,这是由handlerMapping通过执行链来完成的,而具体的映射关系我们在bean定义文件中定义并在HandlerMapping载入上下文的时候就被配置好了。然后 DispatcherServlet调用HandlerMapping来得到对应的执行链,最后通过视图来展现模型数据,但我们要注意的是视图对象是在解析视图名的时候生成配置好的。这些作为核心类的HanderMapping,ViewResolver,View,Handler的紧密协作实现了MVC的功能。
四:spring aop原理:
概念:
advice表示在连接点的行为,要做什么,包括前置增强,后置增强,环绕增强,抛出增强等;
pointcut切点表示要进行行为增强的目标
advisor:将advice和pointcut连接起来,Advisor的实现有:DefaultPointcutAdvisor他有两个属性advice和 pointcut来让我们配置advice和pointcut。
代理对象的生成以ProxyFactoryBean为入口
- public Object getObject() throws BeansException {
- //这里初始化通知器链
- initializeAdvisorChain();
- if (isSingleton()) {
- //根据定义需要生成单件的Proxy
- return getSingletonInstance();
- }
- else {
- .......
- //这里根据定义需要生成Prototype类型的Proxy
- return newPrototypeInstance();
- }
- }
在getSingletonInstance方法钟调用getProxy()生成代理对象
- //使用createAopProxy放回的AopProxy来得到代理对象。
- protected Object getProxy(AopProxy aopProxy) {
- return aopProxy.getProxy(this.beanClassLoader);
- }
AopProxy为一个接口,有两种实现,JdkDynamicAopProxy和ObjenesisCglibAopProxy分别以jdk动态代理技术和cglib动态代理技术生成代理对象
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
//jdk动态代理的类必须实现接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//根据代理的方法和目标类获得advice增强
List
五、spring事务
使用Spring管理事务有声明式和编程式两种方式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码中,使得事务管理代码和业务代码解藕。在这种方式我们结合IoC容器和Spirng已有的FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等。其中最简单的方式就是通过配置TransactionProxyFactoryBean来实现声明式事物;
spring事务的实现最后还是委托给transactionManager来实现,比如在DataSourceTransactionManager:
- protected void doCommit(DefaultTransactionStatus status) {
- //这里得到存在TransactionInfo中已经创建好的事务
- DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
- //这里得到和事务绑定的数据库连接
- Connection con = txObject.getConnectionHolder().getConnection();
- ........
- try {
- //这里通过数据库连接来提交事务
- con.commit();
- }
- .......
- }
- protected void doRollback(DefaultTransactionStatus status) {
- DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
- Connection con = txObject.getConnectionHolder().getConnection();
- if (status.isDebug()) {
- logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
- }
- try {
- //这里通过数据库连接来回滚事务
- con.rollback();
- }
- catch (SQLException ex) {
- throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
- }
- }