前言:
今天各位老铁们对“vardajquery”大体比较关心,看官们都想要剖析一些“vardajquery”的相关文章。那么小编在网上搜集了一些关于“vardajquery””的相关内容,希望小伙伴们能喜欢,我们一起来了解一下吧!接上文简答题一.1.Mybatis动态sql是做什么的?
1.动态sql就是 根据条件标签动态的拼接sql,包括判空,循环,拼接等
2.哪些动态sql?
动态sql大致有
1.: if是为了判断传入的值是否符合某种规则,比如是否不为空;
2.:where标签可以用来做动态拼接查询条件,当和if标签配合的时候,不用显示的声明类似where 1=1这种无用的条件
3.:foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中,
4.:include可以把大量重复的代码整理起来,当使用的时候直接include即可,减少重复代码的编写;
5.:是一个格式化标签
6.choose、when、otherwise 标签类似于 Java 中的 switch、case、default。只有一个条件生效,
<select id="findOneById" resultType="com.lagou.pojo.User"> select <include refid="userInfo"/> from user <where> <if test="id != null and id != 0"> AND id = #{id} </if> <foreach collection="list" item="id" open="(" close=")" separator="," > #{id} </foreach> <trim prefix="where" suffix="order by id" prefixOverrides="and | or" suffixOverrides=","> <if test="name != null and name != ''"> AND name = #{name} </if> <if test="id != null"> AND id = #{id} </if> </trim> </where></select>3. 简述一下动态sql的执行原理?
1.在xmlMapperBuilder中 解析配置文件时
2.解析 <mapper /> 节点
3.解析 节点
// 1.在xmlMapperBuilder中 解析配置文件时 public void parse() { // 解析 `<mapper />` 节点 configurationElement(parser.evalNode("/mapper")); } //2\. 解析 `<mapper />` 节点 private void configurationElement(XNode context) { try { // 获得 namespace 属性 String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.equals("")) { throw new BuilderException("Mapper's namespace cannot be empty"); } // 设置 namespace 属性 builderAssistant.setCurrentNamespace(namespace); // 解析 <resultMap /> 节点们 resultMapElements(context.evalNodes("/mapper/resultMap")); // 解析 <sql /> 节点们 sqlElement(context.evalNodes("/mapper/sql")); // 解析 <select /> <insert /> <update /> <delete /> 节点们 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); } } // 3.解析 <select /> <insert /> <update /> <delete /> 节点们 private void buildStatementFromContext(List<XNode> list) { if (configuration.getDatabaseId() != null) { buildStatementFromContext(list, configuration.getDatabaseId()); } buildStatementFromContext(list, null); // 上面两块代码,可以简写成 buildStatementFromContext(list, configuration.getDatabaseId()); } private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) { //遍历 <select /> <insert /> <update /> <delete /> 节点们 for (XNode context : list) { // 创建 XMLStatementBuilder 对象,执行解析 final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); try { statementParser.parseStatementNode(); } catch (IncompleteElementException e) { // 解析失败,添加到 configuration 中 configuration.addIncompleteStatement(statementParser); } } }
4.XMLStatementBuilder对象
public class XMLStatementBuilder extends BaseBuilder { /** * 执行解析 */ public void parseStatementNode() { // 获得 id 属性,编号。 String id = context.getStringAttribute("id"); // 获得 databaseId , 判断 databaseId 是否匹配 String databaseId = context.getStringAttribute("databaseId"); if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) { return; } // 获得各种属性 Integer fetchSize = context.getIntAttribute("fetchSize"); Integer timeout = context.getIntAttribute("timeout"); String parameterMap = context.getStringAttribute("parameterMap"); String parameterType = context.getStringAttribute("parameterType"); Class<?> parameterTypeClass = resolveClass(parameterType); String resultMap = context.getStringAttribute("resultMap"); String resultType = context.getStringAttribute("resultType"); String lang = context.getStringAttribute("lang"); // 获得 lang 对应的 LanguageDriver 对象 LanguageDriver langDriver = getLanguageDriver(lang); // 获得 resultType 对应的类 Class<?> resultTypeClass = resolveClass(resultType); // 获得 resultSet 对应的枚举值 String resultSetType = context.getStringAttribute("resultSetType"); ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType); // 获得 statementType 对应的枚举值 StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));}
5.LanguageDriver的实现类XMLLanguageDriver的方法解析方法createSqlSource
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) { // 创建 XMLScriptBuilder 对象,执行解析 XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType); return builder.parseScriptNode(); }
6.解析
XMLScriptBuilder标签解析/** * XML 动态语句( SQL )构建器,负责将 SQL 解析成 SqlSource 对象 * * @author Clinton Begin */public class XMLScriptBuilder extends BaseBuilder { /** * 当前 SQL 的 XNode 对象 */ private final XNode context; /** * 是否为动态 SQL */ private boolean isDynamic; /** * SQL 方法类型 */ private final Class<?> parameterType; /** * NodeNodeHandler 的映射 */ private final Map<String, NodeHandler> nodeHandlerMap = new HashMap<>(); public XMLScriptBuilder(Configuration configuration, XNode context) { this(configuration, context, null); } public XMLScriptBuilder(Configuration configuration, XNode context, Class<?> parameterType) { super(configuration); this.context = context; this.parameterType = parameterType; // 初始化 nodeHandlerMap 属性 initNodeHandlerMap(); } /** * 初始化 {@link #nodeHandlerMap} 属性 */ private void initNodeHandlerMap() { nodeHandlerMap.put("trim", new TrimHandler()); nodeHandlerMap.put("where", new WhereHandler()); nodeHandlerMap.put("set", new SetHandler()); nodeHandlerMap.put("foreach", new ForEachHandler()); nodeHandlerMap.put("if", new IfHandler()); nodeHandlerMap.put("choose", new ChooseHandler()); nodeHandlerMap.put("when", new IfHandler()); nodeHandlerMap.put("otherwise", new OtherwiseHandler()); nodeHandlerMap.put("bind", new BindHandler()); } /** * 负责将 SQL 解析成 SqlSource 对象 * * @return SqlSource 对象 */ public SqlSource parseScriptNode() { // 解析 SQL MixedSqlNode rootSqlNode = parseDynamicTags(context); // 创建 SqlSource 对象 SqlSource sqlSource; if (isDynamic) { sqlSource = new DynamicSqlSource(configuration, rootSqlNode); } else { sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType); } return sqlSource; } /** * 解析 SQL 成 MixedSqlNode 对象 * * @param node XNode 节点 * @return MixedSqlNode */ protected MixedSqlNode parseDynamicTags(XNode node) { // 创建 SqlNode 数组 List<SqlNode> contents = new ArrayList<>(); // 遍历 SQL 节点的所有子节点 NodeList children = node.getNode().getChildNodes(); for (int i = 0; i < children.getLength(); i++) { // 当前子节点 XNode child = node.newXNode(children.item(i)); // 如果类型是 Node.CDATA_SECTION_NODE 或者 Node.TEXT_NODE 时 if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) { // 获得内容 String data = child.getStringBody(""); // 创建 TextSqlNode 对象 TextSqlNode textSqlNode = new TextSqlNode(data); // 如果是动态的 TextSqlNode 对象 if (textSqlNode.isDynamic()) { // 添加到 contents 中 contents.add(textSqlNode); // 标记为动态 SQL isDynamic = true; // 如果是非动态的 TextSqlNode 对象 } else { // 创建 StaticTextSqlNode 添加到 contents 中 contents.add(new StaticTextSqlNode(data)); } // 如果类型是 Node.ELEMENT_NODE } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 // 根据子节点的标签,获得对应的 NodeHandler 对象 String nodeName = child.getNode().getNodeName(); NodeHandler handler = nodeHandlerMap.get(nodeName); if (handler == null) { // 获得不到,说明是未知的标签,抛出 BuilderException 异常 throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); } // 执行 NodeHandler 处理 handler.handleNode(child, contents); // 标记为动态 SQL isDynamic = true; } } // 创建 MixedSqlNode 对象 return new MixedSqlNode(contents); } /** * Node 处理器接口 */ private interface NodeHandler { /** * 处理 Node * * @param nodeToHandle 要处理的 XNode 节点 * @param targetContents 目标的 SqlNode 数组。实际上,被处理的 XNode 节点会创建成对应的 SqlNode 对象,添加到 targetContents 中 */ void handleNode(XNode nodeToHandle, List<SqlNode> targetContents); } /** * `<bind />` 标签的处理器 * * @see VarDeclSqlNode */ private class BindHandler implements NodeHandler { public BindHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析 name、value 属性 final String name = nodeToHandle.getStringAttribute("name"); final String expression = nodeToHandle.getStringAttribute("value"); // 创建 VarDeclSqlNode 对象 final VarDeclSqlNode node = new VarDeclSqlNode(name, expression); // 添加到 targetContents 中 targetContents.add(node); } } /** * `<trim />` 标签的处理器 * * @see TrimSqlNode */ private class TrimHandler implements NodeHandler { public TrimHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析内部的 SQL 节点,成 MixedSqlNode 对象 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); // 获得 prefix、prefixOverrides、"suffix"、suffixOverrides 属性 String prefix = nodeToHandle.getStringAttribute("prefix"); String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides"); String suffix = nodeToHandle.getStringAttribute("suffix"); String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides"); // 创建 TrimSqlNode 对象 TrimSqlNode trim = new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides); // 添加到 targetContents 中 targetContents.add(trim); } } /** * `<where />` 标签的处理器 * * @see WhereSqlNode */ private class WhereHandler implements NodeHandler { public WhereHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析内部的 SQL 节点,成 MixedSqlNode 对象 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); // 创建 WhereSqlNode 对象 WhereSqlNode where = new WhereSqlNode(configuration, mixedSqlNode); // 添加到 targetContents 中 targetContents.add(where); } } /** * `<set />` 标签的处理器 * * @see SetSqlNode */ private class SetHandler implements NodeHandler { public SetHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析内部的 SQL 节点,成 MixedSqlNode 对象 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); // 创建 SetSqlNode 对象 SetSqlNode set = new SetSqlNode(configuration, mixedSqlNode); // 添加到 targetContents 中 targetContents.add(set); } } /** * `<foreach />` 标签的处理器 * * @see ForEachSqlNode */ private class ForEachHandler implements NodeHandler { public ForEachHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析内部的 SQL 节点,成 MixedSqlNode 对象 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); // 获得 collection、item、index、open、close、separator 属性 String collection = nodeToHandle.getStringAttribute("collection"); String item = nodeToHandle.getStringAttribute("item"); String index = nodeToHandle.getStringAttribute("index"); String open = nodeToHandle.getStringAttribute("open"); String close = nodeToHandle.getStringAttribute("close"); String separator = nodeToHandle.getStringAttribute("separator"); // 创建 ForEachSqlNode 对象 ForEachSqlNode forEachSqlNode = new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator); // 添加到 targetContents 中 targetContents.add(forEachSqlNode); } } /** * `<if />` 标签的处理器 * * @see IfSqlNode */ private class IfHandler implements NodeHandler { public IfHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析内部的 SQL 节点,成 MixedSqlNode 对象 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); // 获得 test 属性 String test = nodeToHandle.getStringAttribute("test"); // 创建 IfSqlNode 对象 IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test); // 添加到 targetContents 中 targetContents.add(ifSqlNode); } } /** * `<otherwise />` 标签的处理器 */ private class OtherwiseHandler implements NodeHandler { public OtherwiseHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { // 解析内部的 SQL 节点,成 MixedSqlNode 对象 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); // 添加到 targetContents 中 targetContents.add(mixedSqlNode); } } /** * `<choose />` 标签的处理器 * * @see ChooseSqlNode */ private class ChooseHandler implements NodeHandler { public ChooseHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { List<SqlNode> whenSqlNodes = new ArrayList<>(); List<SqlNode> otherwiseSqlNodes = new ArrayList<>(); // 解析 `<when />` 和 `<otherwise />` 的节点们 handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes); // 获得 `<otherwise />` 的节点 SqlNode defaultSqlNode = getDefaultSqlNode(otherwiseSqlNodes); // 创建 ChooseSqlNode 对象 ChooseSqlNode chooseSqlNode = new ChooseSqlNode(whenSqlNodes, defaultSqlNode); // 添加到 targetContents 中 targetContents.add(chooseSqlNode); } private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List<SqlNode> ifSqlNodes, List<SqlNode> defaultSqlNodes) { List<XNode> children = chooseSqlNode.getChildren(); for (XNode child : children) { String nodeName = child.getNode().getNodeName(); NodeHandler handler = nodeHandlerMap.get(nodeName); if (handler instanceof IfHandler) { // 处理 `<when />` 标签的情况 handler.handleNode(child, ifSqlNodes); } else if (handler instanceof OtherwiseHandler) { // 处理 `<otherwise />` 标签的情况 handler.handleNode(child, defaultSqlNodes); } } } // 至多允许有一个 SqlNode 节点 private SqlNode getDefaultSqlNode(List<SqlNode> defaultSqlNodes) { SqlNode defaultSqlNode = null; if (defaultSqlNodes.size() == 1) { defaultSqlNode = defaultSqlNodes.get(0); } else if (defaultSqlNodes.size() > 1) { throw new BuilderException("Too many default (otherwise) elements in choose statement."); } return defaultSqlNode; } }}二、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
延迟加载主要通过动态代理实现,通过代理拦截指定方法没执行数据加载。
javassisProxyFactory会创建一个User代理对象,所有调用User对象方法,都会经过EnhancedResultObjectProxyImpl.invoke()方法的拦截。、
于是当调用User.getOrder()方法时,才真正去执行查询Order的动作并把结果赋值
<settings> <!-- 开启全局配置的懒加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 关闭积极加载 --> <setting name="aggressiveLazyLoading" value="false"/> </settings><mapper namespace="demo.cyj.dao.TeacherDao"> <select id="findTeacherByTname" resultType="Teacher" resultMap="getTeacher"> select t.t_id t_id,t.t_name t_name from teacher t where t.t_name =#{name} </select> //延迟加载 <resultMap type="Teacher" id="getTeacher"> <collection ofType="Student" property="stuList" fetchType="lazy" column="t_name" select="findTeacherByTnameLazy" /> </resultMap> <select id="findTeacherByTnameLazy" resultType="Student" > select s.id id,s.stu_name stu_name,s.stu_age age,s.t_id t_id from student s left join teacher t on t.t_id = s.t_id where t.t_name=#{name} </select> </mapper>2.延迟加载的类
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId()); if (closed) { throw new ExecutorException("Executor was closed."); } if (queryStack == 0 && ms.isFlushCacheRequired()) { clearLocalCache(); } List<E> list; try { queryStack++; list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; if (list != null) { handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { queryStack--; } if (queryStack == 0) { for (DeferredLoad deferredLoad : deferredLoads) { deferredLoad.load(); } // issue #601 deferredLoads.clear(); if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { // issue #482 clearLocalCache(); } } return list; }
延迟加载的类
private static class DeferredLoad { private final MetaObject resultObject; private final String property; private final Class<?> targetType; private final CacheKey key; private final PerpetualCache localCache; private final ObjectFactory objectFactory; private final ResultExtractor resultExtractor; // issue #781 public DeferredLoad(MetaObject resultObject, String property, CacheKey key, PerpetualCache localCache, Configuration configuration, Class<?> targetType) { this.resultObject = resultObject; this.property = property; this.key = key; this.localCache = localCache; this.objectFactory = configuration.getObjectFactory(); this.resultExtractor = new ResultExtractor(configuration, objectFactory); this.targetType = targetType; } public boolean canLoad() { return localCache.getObject(key) != null && localCache.getObject(key) != EXECUTION_PLACEHOLDER; } public void load() { @SuppressWarnings( "unchecked" ) // we suppose we get back a List List<Object> list = (List<Object>) localCache.getObject(key); Object value = resultExtractor.extractObjectFromList(list, targetType); resultObject.setValue(property, value); } }三1.Mybatis都有哪些Executor执行器
BaseExecutor 简单执行器,是 MyBatis 中默认使用的执行器,每执行一次 update 或 select,就开启一个 Statement 对象,用完就直接关闭 Statement 对象(可以是 Statement 或者是 PreparedStatment 对象)
BatchExecutor 批处理执行器,用于将多个SQL一次性输出到数据库
simpleExexutor 每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
ReuseExecutor 执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
cachingExecutor 更新缓存2.它们之间的区别是什么?
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
默认是SimplExcutor,需要配置在创建SqlSession对象的时候指定执行器的类型即可。
四1.一级缓存
Mybatis的一级缓存是指SqlSession级别的,作用域是SqlSession,Mybatis默认开启一级缓存,在同一个SqlSession中,相同的Sql查询的时候,第一次查询的时候,就会从缓存中取,如果发现没有数据,那么就从数据库查询出来,并且缓存到HashMap中,如果下次还是相同的查询,就直接从缓存中查询,就不在去查询数据库,对应的就不在去执行SQL语句。当查询到的数据,进行增删改的操作的时候,缓存将会失效
2. 二级缓存
MyBatis的二级缓存是基于Mapper级别的,也就是说多个SqlSession去使用某个Mapper的查询语句时,得到的缓存数据是可共用的。第一次调用mapper下的sql 的时候去查询信息,查询到的信息会存放到该mapper对应的二级缓存区域,第二次调用namespace下的mapper映射文件中,相同的SQL去查询,回去对应的二级缓存内取结果。二级缓存开启后,查询就会走二级缓存,没查到直接查库。MyBatis默认不开启二级缓存
五
简述Mybatis的插件运行原理,以及如何编写一个插件?
插件运行原理
实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可
实现Interceptor接口 在定义StatementHandler处理器的时候拦截prepare方法也就是准备的方法
//1.configuration.newStatementHandler()获取对象 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; Configuration configuration = ms.getConfiguration(); //定义StatementHandler处理器 StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); //初始化 stmt = prepareStatement(handler, ms.getStatementLog()); //执行 return handler.update(stmt); } //2.获取执行sql的StatementHandler组件 public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); //代理对象 statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); return statementHandler; } //3. 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; } }如何编写插件
实现Interceptor接口,Interceptors注解表明要拦截的类,方法,参数
package com.lagou.plugin;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.plugin.*;import java.sql.Connection;import java.util.Properties; @Intercepts({ @Signature(type= StatementHandler.class,//拦截那个接口 method = "prepare",//这个接口内的那个方法名 args={Connection.class,Integer.class})//拦截方法的入参,如果方法重载,通过方法名跟参数确定唯一 }) public class MyPlugin implements Interceptor { //这里是每次执行操作的时候,都会进行这个方法 @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("增强了"); return invocation.proceed(); } //把这个拦截器生成一个代理放到拦截器链中 @Override public Object plugin(Object target) { System.out.println("将要包装的目标对象"+target); return Plugin.wrap(target,this); } //插件初始化时候调用,只调用一次 获取配置文件的属性 @Override public void setProperties(Properties properties) { System.out.println("获取配置文件的属性"+properties); } }tementHandler); return statementHandler; } //3. 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; } }如何编写插件
实现Interceptor接口,Interceptors注解表明要拦截的类,方法,参数
package com.lagou.plugin;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.plugin.*;import java.sql.Connection;import java.util.Properties; @Intercepts({ @Signature(type= StatementHandler.class,//拦截那个接口 method = "prepare",//这个接口内的那个方法名 args={Connection.class,Integer.class})//拦截方法的入参,如果方法重载,通过方法名跟参数确定唯一 }) public class MyPlugin implements Interceptor { //这里是每次执行操作的时候,都会进行这个方法 @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("增强了"); return invocation.proceed(); } //把这个拦截器生成一个代理放到拦截器链中 @Override public Object plugin(Object target) { System.out.println("将要包装的目标对象"+target); return Plugin.wrap(target,this); } //插件初始化时候调用,只调用一次 获取配置文件的属性 @Override public void setProperties(Properties properties) { System.out.println("获取配置文件的属性"+properties); } }结尾
上下两部分已经更完了,本文到这里就结束了,感谢看到最后的朋友,都看到最后了,点个赞再走啊,如有不对之处还请多多指正。
标签: #vardajquery