在之前我们知道configuration创建过程中调用了private void parseConfiguration(XNode root) 这个方法,其中有一句pluginElement(root.evalNode("plugins"));方法,这个就是读取配置的插件的;
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String interceptor = child.getStringAttribute("interceptor");
Properties properties = child.getChildrenAsProperties();
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
interceptorInstance.setProperties(properties);
configuration.addInterceptor(interceptorInstance);
}
}
}
从中看到这句:
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
对,这就是插件在mybatis上下文初始化过程中,就读入插件节点和配置的参数,它通过反射技术生成插件实例;
configuration.addInterceptor(interceptorInstance);
将插件放入到configuration中,继续跟进:
public class InterceptorChain {
private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
public void addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
}
public List<Interceptor> getInterceptors() {
return Collections.unmodifiableList(interceptors);
}
}
最后将插件保存到了一个list对象里面等待被调用。
这里有个插件接口需要说一下那就是Interceptor,进入其中:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
这个接口里面就只有三个方法,那我们来介绍一下各个方法的作用:
1)intercept()方法是插件的核心方法,它将拦截的对象直接覆盖原有的方法;
2)plugin()方法是为被拦截的对象生成一个代理对象,并返回它;这里多说明一下,mybatis提供了org.apache.ibatis.plugin.Plugin中的wrap静态方法生成代理对象;
3)setProperties()允许在plugin元素中配置所有参数;
我们在获取四大对象的时候都会调用
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
这里的plugin()就是接口中的方法2),目的就是生成代理对象的;