继续上一篇的mybatis的分页插件。
我尝试了一下,不管怎么配置mybatis.xml文件都会导致spring不能正确的将我的插件类加载到内存中并且添加到configuration的插件链中。所以果断的放弃了使用xml配置的想法。
一维我之前也写过从ioc-di-dop-url映射的一整套流程,所以我知道那个放置bean的地方一定是可以获取的。
所以我知道其大致的流程:
首先第一种方法,请各位移步这里:
https://www.jianshu.com/p/9aa9df030109
这位博主将的很好,我就不献丑了我试试分析一下。
文章中说的实现ApplicationContextAware接口即可。
那么具体是在哪里被实例化的呢?
首先在AbstractApplicationContext中的refresh方法中的this.prepareBeanFactory(beanFactory)函数里有详解。
还是同一个类的方法:
画红色的部分就是了。
可以看到当前的这里set中有9个元素:
具体的实例化笔者没有找到,感兴趣的读者可以去找下。
好了现在来说下我的方法了,不需要配置,不需要实现任何接口就可以实现想要的功能了。可以将整个的DefaultListableBeanFactory拿到(如果雷同纯属巧合),这个是我在讨厌mybatis的插件的配置失败情况下的产物吧!
还是那个refresh的函数:
从上图可以知道了所有的信息都是放在了这个defaultlistableBeanFactory中的。
所以只要拿到了这个就可以了。为什么挑选这个类呢?
1.在程序的运转中这个类是直接被用到的,且他也是确确实实的承载着bean信息的类。
2.选择它是有一个好处的,就是它自带了一个static的变量,恰巧这个变量的内置类型还是defaultlistableBeanFactory的,所以这样就可以非常轻松的拿取到所需要的数据了。
3.java对于静态属性的变量有一个特性,就是通过反射拿去具体的值时不需要具体的实例,其实也很好理解,应为这哥变量是类的,所以不需要实例,如果有不懂的同学,可以去看下类的加载过程就可以了。
附图:
所以开整了!
//这个是我的一个service层的一个函数
public UserVo findall() throws Exception {
//拿取到DefaultListableBeanFactory类的class文件
Class<DefaultListableBeanFactory> defaultListableBeanFactoryClass = DefaultListableBeanFactory.class;
//拿取具体的变量,即上图中被圈出来的那个static变量
Field serializableFactories = defaultListableBeanFactoryClass.getDeclaredField("serializableFactories");
//设置权限
serializableFactories.setAccessible(true);
//拿取到具体的属性
Map<String, Reference<DefaultListableBeanFactory>> o = (Map<String, Reference<DefaultListableBeanFactory>>)serializableFactories.get(null);
//拿取值的set集合
Set<Map.Entry<String, Reference<DefaultListableBeanFactory>>> entries = o.entrySet();
Iterator<Map.Entry<String, Reference<DefaultListableBeanFactory>>> iterator = entries.iterator();
//遍历iterator
while (iterator.hasNext()){
//拿取元素
Map.Entry<String, Reference<DefaultListableBeanFactory>> next = iterator.next();
System.out.println(next.getKey()+" "+next.getValue());
//拿取Reference值
Reference<DefaultListableBeanFactory> value = next.getValue();
//拿取Reference中的value,也就是DefaultListableBeanFactory
//至此已经拿到了想要的数据了
DefaultListableBeanFactory defaultListableBeanFactory = value.get();
assert defaultListableBeanFactory != null;
//通过getBean(String beanname)获取具体的bean
//sqlSessionFactory就是在dao的配置文件里配置的用于管理session的
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory)defaultListableBeanFactory.getBean("sqlSessionFactory");
//拿取configuration,终于拿到了,不容易啊,这个才是最想拿到的
Configuration configuration = sqlSessionFactory.getConfiguration();
//添加自定义的插件,至此自定义的插件已经被加入了
configuration.addInterceptor(new testInterceptor());
}
UserVo vo = new UserVo();
vo.setUser(ud.queryall());
return vo;
}
附上我的简单的插件:
具体的插件装载初始化到使用,在上一篇文章中都已分析了,这里不再赘述。
@Intercepts( {
@Signature(method = "prepare", type=StatementHandler.class, args = {Connection.class,Integer.class}) })
public class testInterceptor implements Interceptor {
String prop1;
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("");
StatementHandler target = (StatementHandler)invocation.getTarget();
BoundSql boundSql = target.getBoundSql();
String sql = boundSql.getSql();
System.out.println(sql);
sql+=" limit 0,10";
Class<? extends BoundSql> aClass = boundSql.getClass();
Field sql1 = aClass.getDeclaredField("sql");
sql1.setAccessible(true);
sql1.set(boundSql,sql);
System.out.println(boundSql.getSql());
System.out.println("///");
// this.notifyAll();
return invocation.proceed();
}
@Override
public Object plugin(Object o) {
return Plugin.wrap(o,this);
}
@Override
public void setProperties(Properties properties) {
prop1 = properties.getProperty("prop1");
}
}
来看下效果吧:
从图中的效果发现已经成功了,成功地将读取所有的元素改成了只读取前10个。
但是这个有一个缺点,虽然说这个缺点还没有暴露出来就是在DefaultListableBeanFactory的那个静态变量是一个弱引用,也就是在下一次gc的时候回被回收,所以如果是在gc回收之后再去获取那么就有可能获取不到这个变量的值。
但是如果在程序启动后就去获取,那么就可以获取到,因为不可能ssm项目刚启动就开始了gc。如果开启了gc,那么只能说你的jvm的堆和栈的配置太小了,或者说你的不是jdk1.8,应为1.8之前都是有一个永久代的。方法区就在这里,所以会出现这种情况,但是1.8后将类的元数据放到了直接内存中。所以如果还是出现了gc,那么 只能说你的内存整的太小了,或者说你开了太多的东西,留给jvm的空间不够。
所以一般情况下都是能够获取的。
为什么不挑选第一种方案呢?只能说我就是应为配置mybatis的配置文件失败的:
我寻思和网上的一毛一样啊,为什么,总是获取不到具体的插件呢?
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="com.test.testInterceptor">
<property name="prop1" value="prop1"/>
</plugin>
</plugins>
</configuration>
失败了很多次后对于配置文件彻底丧失了信心,所以只能投机取巧了。
但是我的这个办法不失为一种好的办法(哈哈哈,自恋一下)。
如转载,请说明出处!