参考1:https://blog.csdn.net/eternity_xyf/article/details/78531834
/**
* Parses a key-value pair into a key-object pair.
*
* <p>This class is intended to be subclassed. Subclasses need declare the key in which they parse,
* and the type of object they parse into.
*
* <p>Instances need to be declared in a spring context like the following:
*
* <pre>
* <code>
* <bean id="myKvpParser" class="org.xzy.MyKvpParser"/>
* </code>
* </pre>
*
* Where <code>com.xzy.MyKvpParser</code> could be something like:
*
* <pre>
* <code>
* public class MyKvpParser extends KvpParser {
*
* public MyKvpParser() {
* super( "MyKvp", MyObject.class )l
* }
*
* public Object parse( String value ) {
* return new MyObject( value );
* }
* }
* </code>
* </pre>
*
* <p><b>Operation Binding</b>
*
* <p>In the normal case, a kvp parser is engaged when a request specifies a name which matches the
* name declared by the kvp parser. It is also possible to attach a kvp parser so that it only
* engages on a particular operation. This is done by declaring the one or more of the following:
*
* <ul>
* <li>service
* <li>version
* <li>request
* </ul>
*
* <p>When a kvp parser declares one or more of these properties, it will only be engaged if an
* incoming request specicfies matching values of the properties.
*
* <p>The following bean declaration would create the above kvp parser so that it only engages when
* the service is "MyService", and the request is "MyRequest".
*
* <pre>
* <code>
* <bean id="myKvpParser" class="org.xzy.MyKvpParser">
* <property name="service">MyService</property>
* <property name="request">MyRequest</property>
* <bean>
* </code>
* </pre>
*
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
*/
可以看出,这其实是一个虚函数。。
一个实现它的类FormatOptionsKvpParser extends KvpParser,主要是实现parse()方法。
@Override
public Object parse(String value) throws Exception {
Map<String, Object> formatOptions = new CaseInsensitiveMap<>(new TreeMap<>());
List<String> kvps = KvpUtils.escapedTokens(value, ';');
List parsers = GeoServerExtensions.extensions(KvpParser.class, applicationContext);
for (String kvp : kvps) {
List<String> kv = KvpUtils.escapedTokens(kvp, ':', 2);
String key = kv.get(0);
String raw = kv.size() == 1 ? "true" : KvpUtils.unescape(kv.get(1));
Object parsed = null;
for (Object o : parsers) {
KvpParser parser = (KvpParser) o;
if (key.equalsIgnoreCase(parser.getKey())) {
parsed = parser.parse(raw);
if (parsed != null) {
break;
}
}
}
if (parsed == null) {
if (LOGGER.isLoggable(Level.FINER))
LOGGER.finer(
"Could not find kvp parser for: '" + key + "'. Storing as raw string.");
parsed = raw;
}
formatOptions.put(key, parsed);
}
return formatOptions;
}
可以看出,这里调用GeoServerExtensions.extensions(KvpParser.class, applicationContext)注册KvpParser类到扩展中。这样做的好处是,下次就可以直接调用,不需要重新初始化了吗?(工厂模式的Registry)。那为什么不直接getbean。。
>>KvpRequestReader
findKvpRequestReader(Class<?> type):寻找KvpRequestReader,可以接收任意类型的类为参数,这里以Message.class为例。
首先调用loadKvpRequestReaders,加载所有的KvpRequestReaders。。
public static Collection<KvpRequestReader> loadKvpRequestReaders() {
Collection<KvpRequestReader> kvpReaders =
GeoServerExtensions.extensions(KvpRequestReader.class);
if (!(new HashSet<>(kvpReaders).size() == kvpReaders.size())) {
String msg = "Two identical kvp readers found";
throw new IllegalStateException(msg);
}
return kvpReaders;
}
当然在查找之前,肯定要先加载bean。。也就是applicationContext.xml,
URL url = getClass().getResource("applicationContext.xml");
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(url.toString())
Dispatcher dispatcher = (Dispatcher) context.getBean("dispatcher");
所以是怎么在extensions中通过KvpRequestReader找到MessageKvpRequestReader的?
public class MessageKvpRequestReader extends KvpRequestReader {
public MessageKvpRequestReader() {
super(Message.class);
}
@Override
public Object createRequest() {
return new Message();
}
}
可以看出MessageKvpRequestReader是KvpRequestReader的子类。。
context.getBeanNamesForType(extensionPoint);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2021-01-18 SQL Server空间数据库之:起点和终点的XY怎么查?
2021-01-18 SQL Server CLR调用C#自定义函数
2021-01-18 SQL Server内部有投影变换函数吗?能进行坐标系的变换吗?
2021-01-18 为什么需要空间索引(Spatial Reference)?
2019-01-18 Kinect相机位姿