在之前我们知道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),目的就是生成代理对象的;