Dubbo 소스 분석 - 필터 (1) 의 ClassLoader Filter
2635 단어 dubbo 원본 코드 분석
1. 개요
ProtocolFilterWrapper에서 서비스 인용과 노출 시 #buildInvokerChain(invoker,key,group) 방법은 Dubbo SPI Active 메커니즘을 바탕으로 일치하는 필터 그룹을 불러오고 필터 체인이 있는 Invoker 대상을 만듭니다.코드는 다음과 같습니다./**
* Filter Invoker
*
* @param invoker Invoker
* @param key URL
* @param group
* @param
* @return Invoker
*/
private static Invoker buildInvokerChain(final Invoker invoker, String key, String group) {
Invoker last = invoker;
//
List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
// Filter , Filter Invoker
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker next = last;
last = new Invoker() {
@Override
public Class getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
2.ClassLoaderFilter
Filter 인터페이스를 구현하고 클래스 로더에서 필터 구현 클래스를 전환합니다.코드는 다음과 같습니다.@Activate(group = Constants.PROVIDER, order = -30000)
public class ClassLoaderFilter implements Filter {
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
//
ClassLoader ocl = Thread.currentThread().getContextClassLoader();
//
Thread.currentThread().setContextClassLoader(invoker.getInterface().getClassLoader());
//
try {
return invoker.invoke(invocation);
} finally {
//
Thread.currentThread().setContextClassLoader(ocl);
}
}
}
설계 목적에서 인터페이스에 정의된 클래스 캐리어를 불러오는 것으로 전환하여 같은 클래스 캐리어의 상하문과 함께 작업을 할 수 있도록 한다.
/**
* Filter Invoker
*
* @param invoker Invoker
* @param key URL
* @param group
* @param
* @return Invoker
*/
private static Invoker buildInvokerChain(final Invoker invoker, String key, String group) {
Invoker last = invoker;
//
List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
// Filter , Filter Invoker
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker next = last;
last = new Invoker() {
@Override
public Class getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
Filter 인터페이스를 구현하고 클래스 로더에서 필터 구현 클래스를 전환합니다.코드는 다음과 같습니다.
@Activate(group = Constants.PROVIDER, order = -30000)
public class ClassLoaderFilter implements Filter {
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
//
ClassLoader ocl = Thread.currentThread().getContextClassLoader();
//
Thread.currentThread().setContextClassLoader(invoker.getInterface().getClassLoader());
//
try {
return invoker.invoke(invocation);
} finally {
//
Thread.currentThread().setContextClassLoader(ocl);
}
}
}
설계 목적에서 인터페이스에 정의된 클래스 캐리어를 불러오는 것으로 전환하여 같은 클래스 캐리어의 상하문과 함께 작업을 할 수 있도록 한다.