在Restlet实战(四)与Spring集成给出了Restlet如何与Spring进行集成。下面就结合Restlet的源码分析一下Spring配置文件。
在Spring的配置文件中,我们能看到这样的代码:
<entry key="/customers"> <bean class="org.restlet.ext.spring.SpringFinder"> <lookup-method name="createResource" bean="customersResource" /> </bean> </entry>
从配置上很容易看出SpringFinder有一个方法:createResource,作用就是实例化在Spring中定义的Resource。看源码中的crateResource方法:
public Resource createResource() { Resource result = null; if (getTargetClass() != null) { try { // Invoke the default constructor result = (Resource) getTargetClass().newInstance(); } catch (Exception e) { getLogger() .log( Level.WARNING, "Exception while instantiating the target resource.", e); } } return result; }
代码如此简单,就不用多做解释了。
接下来,我们看一下另外的一个配置项:
<bean id="restRoute" class="org.restlet.ext.spring.SpringRouter"> <property name="attachments"> <map> <entry key="/customers"> <bean class="org.restlet.ext.spring.SpringFinder"> <lookup-method name="createResource" bean="customersResource" /> </bean> </entry> <entry key="/customers/{customerId}"> <bean class="org.restlet.ext.spring.SpringFinder"> <lookup-method name="createResource" bean="customerResource" /> </bean> </entry> </map> </property> </bean>
是的,接下去就要分析SpringRouter,从上面的配置能看到此类有一个attachments的属性,那么跟这个属性有关的方法就是setAttachments了
public static void setAttachments(Router router, Map<String, Object> routes) { Object value; Class resourceClass; try { for (final String key : routes.keySet()) { value = routes.get(key); if (value instanceof Restlet) { router.attach(key, (Restlet) value); } else if (value instanceof Class) { router.attach(key, (Class<? extends Resource>) value); } else if (value instanceof String) { resourceClass = Engine.loadClass((String) value); if (Resource.class.isAssignableFrom(resourceClass)) { router.attach(key, resourceClass); } else { router .getLogger() .warning( "Unknown class found in the mappings. Only subclasses of org.restlet.resource.Resource are allowed."); } } else { router.getLogger().warning( "Unknown object found in the mappings. Only instances of Restlet and subclasses of org.restlet.resource.Resource are allowed."); } } } catch (ClassNotFoundException e) { router.getLogger().log(Level.WARNING, "Unable to set the router mappings", e); } }
上述代码首先从一个循环开始,从Map里面取出需要的元素。key就上上面配置中的URL了,例如:/customers,/customers/{customerId},而value就是我们配置的相应的bean,程序里首先会check得到的value是不是Restlet的实例,如果是,就把这个value attach到router上,如果不是,则检查这个value是一个class还是一个String类型的字符串。如果是class,则认为这个class必定是一个Resource,直接attach到router;如果是String类型的字符串,则首先会认为是一个指定Resource的字符串,实例化,并attach到router,否则记录警告的日志信息。
看到这里,不知各位是否有想法,当时我看的时候,对第二、三个判断倒是很清晰,无非是把Resource直接attach到Router上,而对于第一个判断,按照上述代码所写,只要是Restlet的实例貌似就可以,换句话说,是不是我定义一个Application也可以作为一个元素配置上去?
限于篇幅的长度以及可读性,下篇给出相关的测试。