这要从DefaultAnnotationHandlerMapping这个类说起,该类被@Component注释,该类被Spring IOC容器实例化之后,将会执行其initApplicationContext方法(该方法在其父类中得到实现)
主要的几个类的继承关系如上图,其中ApplicationObjectSupport是由SpringFrameWork提供的抽象类
上图是ApplicationObjectSupport类中的两个方法,该类实现了ApplicationContextAware接口,并且在setApplicationContext方法中,调用了上图中的initApplicationContext(context)方法做初始化工作(虽然实际上图的实现中什么也没做,但子类却获得了初始化的机会),而该方法又调用了抽象的initApplicationContext()方法,我的AbstractTransactionHandlerMapping类间接实现了ApplicationObjectSupport类,并且initApplicationContext()方法也在该类中得到了实现,这将使得容器完成启动后,AbstractTransactionHandlerMapping的子类对象,也就是我的DefaultAnnotationHandlerMapping对象的initApplicationContext()方法(该方法的具体代码在父类AbstractTransactionHandlerMapping中)将会得到Spring框架的调用
如上图,我的AbstractTransactionHandlerMapping类在initApplicationContext中调用了detectHandlers方法,该方法通过determineTranscodesForHandler(beanName)完成handler的查找,通过registerHandler(transcodes, beanName)完成handler的注册
所以以下分别就这两个步骤进行说明:
1.查找
首先,将Spring容器中所有的Singleton的BeanName取出来,放到String数组中
该数组的内容如上图。
如上图,determineTranscodesForHandler是在AbstractDetectingTransactionHandlerMapping的子类DefaultAnnotationHandlerMapping中实现的
该方法首先拿到容器,根据beanName取得其对应的Class对象,接下来AnnotationUtils.findAnnotation(handlerType, Controller.class)方法可以判断该类是否有Controller注解,如果没有那就说明没有符合要求的handler,如果有,自然要继续往该类的方法里面去找,哪些方法有我定义的@TransactionMapping方法,有了这些方法的Controller才能称之为一个SpringBank的handler
接下来determineTransactionForHandlerMethods里面的处理比较多余,实际上我并不需要去判断接口是否有注解,这里主要是参考并保留了SpringMVC的做法。对我来说,主要的逻辑就是取得Controller的类对象之后,判断一下里面哪些方法有@TransactionMapping注解,并且将注解里的Transaction对应的值取出来,放到一个Set中,最终这个Set的值类似于[Recharge, CreateOwner]
2.注册
当走到registerHandler这个方法时,其参数将会是这样:String[] transcodes = [CreateOwner, Recharge] ; String beanName = transactionController
这一步的处理已经很简单了,就是根据handler的名字取得容器中它的对象,然后以存在handlerMap中,最终handlerMap看起来将会和下面这样差不多:
handlerMap: {CreateOwner=com.springbank.portal.controller.TransactionController@651aed93, Recharge=com.springbank.portal.controller.TransactionController@651aed93}