RESTEasy:「javax.ws.rs.ext.Providers」文件的加载
RESTEasy使用「META-INF/services/javax.ws.rs.ext.Providers」这个文件来设置所要加载的Providers。
在「resteasy-jaxrs」里面设置了默认加载的providers:
$ pwd
/Users/weli/projs/resteasy/resteasy-upstream/resteasy-jaxrs/src
$ find . | grep javax.ws.rs.ext.Providers
./main/resources/META-INF/services/javax.ws.rs.ext.Providers
$ cat ./main/resources/META-INF/services/javax.ws.rs.ext.Providers
org.jboss.resteasy.plugins.providers.DataSourceProvider
org.jboss.resteasy.plugins.providers.DocumentProvider
org.jboss.resteasy.plugins.providers.DefaultTextPlain
org.jboss.resteasy.plugins.providers.DefaultNumberWriter
org.jboss.resteasy.plugins.providers.StringTextStar
org.jboss.resteasy.plugins.providers.SourceProvider
org.jboss.resteasy.plugins.providers.InputStreamProvider
org.jboss.resteasy.plugins.providers.ReaderProvider
org.jboss.resteasy.plugins.providers.ByteArrayProvider
org.jboss.resteasy.plugins.providers.FormUrlEncodedProvider
org.jboss.resteasy.plugins.providers.JaxrsFormProvider
org.jboss.resteasy.plugins.providers.FileProvider
org.jboss.resteasy.plugins.providers.FileRangeWriter
org.jboss.resteasy.plugins.providers.StreamingOutputProvider
org.jboss.resteasy.plugins.providers.IIOImageProvider
org.jboss.resteasy.plugins.interceptors.CacheControlFeature
org.jboss.resteasy.plugins.interceptors.ClientContentEncodingAnnotationFeature
org.jboss.resteasy.plugins.interceptors.ServerContentEncodingAnnotationFeature
org.jboss.resteasy.plugins.interceptors.MessageSanitizerContainerResponseFilter
org.jboss.resteasy.plugins.providers.sse.SseEventProvider
org.jboss.resteasy.plugins.providers.sse.SseEventOutputProvider
org.jboss.resteasy.plugins.providers.sse.SseEventSinkInterceptor
加载的逻辑在「RegisterBuiltin.java」里面:
$ pwd
/Users/weli/projs/resteasy/resteasy-upstream/resteasy-jaxrs/src
$ grep -rl 'META-INF' *
main/java/org/jboss/resteasy/plugins/providers/RegisterBuiltin.java
main/java/org/jboss/resteasy/plugins/providers/SerializableProvider.java
main/java/org/jboss/resteasy/spi/FactoryFinder.java
$ grep 'META-INF' main/java/org/jboss/resteasy/plugins/providers/RegisterBuiltin.java
Enumeration<URL> en = Thread.currentThread().getContextClassLoader().getResources("META-INF/services/" + Providers.class.getName());
如上所示,「RegisterBuiltin」会负责进行providers的加载工作。使用「RegisterBuiltin」的classes如下:
$ grep -rl 'RegisterBuiltin' *
main/java/org/jboss/resteasy/core/ThreadLocalResteasyProviderFactory.java
main/java/org/jboss/resteasy/mock/MockDispatcherFactory.java
main/java/org/jboss/resteasy/plugins/providers/RegisterBuiltin.java
main/java/org/jboss/resteasy/plugins/providers/sse/InboundSseEventImpl.java
main/java/org/jboss/resteasy/plugins/server/servlet/ConfigurationBootstrap.java
main/java/org/jboss/resteasy/spi/ResteasyDeployment.java
main/java/org/jboss/resteasy/spi/ResteasyProviderFactory.java
其中,「ResteasyDeployment」负责给「ResteasyProviderFactory」设置options:
$ grep -i 'builtin' main/java/org/jboss/resteasy/spi/ResteasyDeployment.java
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
protected boolean registerBuiltin = true;
providerFactory.setRegisterBuiltins(registerBuiltin);
// Interceptor preferences should come before provider registration or builtin.
if (registerBuiltin)
providerFactory.setRegisterBuiltins(true);
RegisterBuiltin.register(providerFactory);
providerFactory.setRegisterBuiltins(false);
public boolean isRegisterBuiltin()
return registerBuiltin;
public void setRegisterBuiltin(boolean registerBuiltin)
this.registerBuiltin = registerBuiltin;
而实际的加载部分则在「ResteasyProviderFactory」当中:
$ grep -i 'builtin' main/java/org/jboss/resteasy/spi/ResteasyProviderFactory.java
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
public boolean isBuiltin = false;
private SortedKey(Class<?> intf, T reader, Class<?> readerClass, int priority, boolean isBuiltin)
this.isBuiltin = isBuiltin;
private SortedKey(Class<?> intf, T reader, Class<?> readerClass, boolean isBuiltin)
this.isBuiltin = isBuiltin;
// Sort user provider before builtins
if (isBuiltin == tMessageBodyKey.isBuiltin)
if (isBuiltin) return 1;
public static boolean registerBuiltinByDefault = true;
protected boolean builtinsRegistered = false;
protected boolean registerBuiltins = true;
builtinsRegistered = false;
registerBuiltins = true;
if (registerBuiltinByDefault) RegisterBuiltin.register(instance);
public static void setRegisterBuiltinByDefault(boolean registerBuiltinByDefault)
ResteasyProviderFactory.registerBuiltinByDefault = registerBuiltinByDefault;
public boolean isRegisterBuiltins()
return registerBuiltins;
public void setRegisterBuiltins(boolean registerBuiltins)
this.registerBuiltins = registerBuiltins;
public boolean isBuiltinsRegistered()
return builtinsRegistered;
public void setBuiltinsRegistered(boolean builtinsRegistered)
this.builtinsRegistered = builtinsRegistered;
protected void addMessageBodyReader(Class<? extends MessageBodyReader> provider, int priority, boolean isBuiltin)
addMessageBodyReader(reader, provider, priority, isBuiltin);
protected void addMessageBodyReader(MessageBodyReader provider, int priority, boolean isBuiltin)
addMessageBodyReader(provider, provider.getClass(), priority, isBuiltin);
* @param isBuiltin
protected void addMessageBodyReader(MessageBodyReader provider, Class<?> providerClass, int priority, boolean isBuiltin)
SortedKey<MessageBodyReader> key = new SortedKey<MessageBodyReader>(MessageBodyReader.class, provider, providerClass, priority, isBuiltin);
protected void addMessageBodyWriter(Class<? extends MessageBodyWriter> provider, int priority, boolean isBuiltin)
addMessageBodyWriter(writer, provider, priority, isBuiltin);
* @param isBuiltin
protected void addMessageBodyWriter(MessageBodyWriter provider, Class<?> providerClass, int priority, boolean isBuiltin)
SortedKey<MessageBodyWriter> key = new SortedKey<MessageBodyWriter>(MessageBodyWriter.class, provider, providerClass, priority, isBuiltin);
protected void addContextResolver(Class<? extends ContextResolver> resolver, boolean builtin)
addContextResolver(writer, resolver, builtin);
protected void addContextResolver(ContextResolver provider, boolean builtin)
addContextResolver(provider, provider.getClass(), builtin);
protected void addContextResolver(ContextResolver provider, Class providerClass, boolean builtin)
addContextResolver(provider, parameter, providerClass, builtin);
protected void addContextResolver(ContextResolver provider, Type typeParameter, Class providerClass, boolean builtin)
SortedKey<ContextResolver> key = new SortedKey<ContextResolver>(ContextResolver.class, provider, providerClass, priority, builtin);
if (!list.get(i).isBuiltin)
if (list.get(i).isBuiltin)
public void registerProvider(Class provider, boolean isBuiltin)
registerProvider(provider, null, isBuiltin, null);
public void registerProvider(Class provider, Integer priorityOverride, boolean isBuiltin, Map<Class<?>, Integer> contracts)
processProviderContracts(provider, priorityOverride, isBuiltin, contracts, newContracts);
protected void processProviderContracts(Class provider, Integer priorityOverride, boolean isBuiltin,
addMessageBodyReader(provider, priority, isBuiltin);
addMessageBodyWriter(provider, priority, isBuiltin);
addContextResolver(provider, isBuiltin);
public void registerProviderInstance(Object provider, Map<Class<?>, Integer> contracts, Integer priorityOverride, boolean builtIn)
processProviderInstanceContracts(provider, contracts, priorityOverride, builtIn, newContracts);
Integer priorityOverride, boolean builtIn, Map<Class<?>, Integer> newContracts)
addMessageBodyReader((MessageBodyReader) provider, priority, builtIn);
addMessageBodyWriter((MessageBodyWriter) provider, provider.getClass(), priority, builtIn);
以上是对于providers加载方面的分析。