Responsibility chain Model
The definition of the responsibility chain pattern: Multiple objects have the opportunity to process the request, thus avoiding the coupling between the sender and the recipient of the request, linking the object to a chain, and passing the request along the chain until an object is processed by him. There is no longer too much to introduce what is the responsibility chain model, mainly to say how to write in Java. This is mainly described in the code in the following 3 frameworks.
- Filter in a servlet
- Filter in the Dubbo
- MyBatis in the plugin of the 3 frameworks in the implementation of the chain of responsibility is not the same way.
Filter in a servlet
The servlet defines a filter and Filterchain interface, the core code is as follows:
12345678910111213141516171819 |
public
final
class
ApplicationFilterChain
implements
FilterChain {
private
int
pos =
0
;
//当前执行filter的offset
private
int
n;
//当前filter的数量
private
ApplicationFilterConfig[] filters;
//filter配置类,通过getFilter()方法获取Filter
private
Servlet servlet
@Override
public
void
doFilter(ServletRequest request, ServletResponse response) {
if
(pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = filterConfig.getFilter();
filter.doFilter(request, response,
this
);
}
else
{
// filter都处理完毕后,执行servlet
servlet.service(request, response);
}
}
}
|
The code is simple and the structure is clearer, defining a chain that contains the filter list and the servlet to make various filter logic before invoking the real servlet.
Filter in the Dubbo
Dubbo is another way to create a filter, by encapsulating the filter into an anonymous class of Invoker, through a data structure such as a linked list to complete the chain of responsibility, the core code is as follows:
12345678910111213141516171819 |
private
static
<T> Invoker<T> buildInvokerChain(
final
Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
//只获取满足条件的Filter
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.
class
).getActivateExtension(invoker.getUrl(), key, group);
if
(filters.size() >
0
) {
for
(
int i = filters.size() -
1
; i >=
0
; i --) {
final
Filter filter = filters.get(i);
final
Invoker<T> next = last;
last =
new
Invoker<T>() {
...
public
Result invoke(Invocation invocation)
throws
RpcException {
return filter.invoke(next, invocation);
}
...
};
}
}
return last;
}
|
Dubbo's chain of responsibility does not have a class like filterchain. Filter and call Invoker are combined, but by creating a linked list, when called We only know the first node, each node contains the node information of the next call. Although the Invoker package filter does not show the specified next, it achieves the same effect through the Java anonymous class and final mechanism.
The plugin in MyBatis
MyBatis can configure a variety of plugin, whether it is officially provided or defined by itself, plugin and filter are similar, do some things in the execution of SQL statements. The responsibility chain of MyBatis is the actual executor class using the plugin agent by means of dynamic proxy. (The combination mode is actually used here, because plugin can nest proxies), the core code is as follows:
12345678910111213141516171819202122232425 |
public
class
Plugin
implements
InvocationHandler{
private
Object target;
private
Interceptor interceptor;
@Override
public
Object invoke(Object proxy, Method method, Object[] args)
throws
Throwable {
if
(满足代理条件) {
return
interceptor.intercept(
new
Invocation(target, method, args));
}
return method.invoke(target, args);
}
//对传入的对象进行代理,可能是实际的Executor类,也可能是Plugin代理类
public
static
Object wrap(Object target, Interceptor interceptor) {
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if
(interfaces.length >
0
) {
return
Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new
Plugin(target, interceptor, signatureMap));
}
return
target;
}
}
|
The following are simple:
Summarize
Here is a brief introduction to the Servlet, Dubbo, MyBatis different ways to implement the responsibility chain model, in which the servlet is relatively clear, and easy to implement the way, while Dubbo and MyBatis is suitable for the original code based on the code to increase the responsibility chain mode of the least amount of change.
The above is forwarded to others.
The following is a personal simulation implementation
Filters in 1.web filter Many people understand, so do not do simulation
Filter in 2.dubbo
public void Test () { list<filter> lists = new arraylist<> (); Lists.add (New Sayworldfilter ()); Lists.add (New Sayhellofilter ()); Request Request = new Myrequest (); for (Filter filter:lists) { request next = Request; Request = new request () { @Override public String test () { return filter.filter (next);}} ; request.test (); }
3.mybatis use of dynamic agent production of packaging classes to implement filtering
Request Request = (Request) (Requestwrap.wrap (New Myrequest (), New Sayworldfilter ())); Request = (Request) (Requestwrap.wrap (Request, New Sayhellofilter ())); Request.test ();
See the attached code for details.
Https://files.cnblogs.com/files/z-test/filter.rar
Three implementations of the Java responsibility Chain model