衡水建设公司网站PHP网站开发简单实例
衡水建设公司网站,PHP网站开发简单实例,企业网站seo推广,淄博建设网站公司下面的代码#xff0c;照着复制就能跑起来
今天看了下Spring的Configuration#xff0c;即java类配置bean,#xff08;这个spring3的新功能#xff0c;虽然现在已经spring5了#xff0c;但是这种配置bean的方式也是比较火的#xff09; 做了如下测试#xff0c;发现一个…下面的代码照着复制就能跑起来
今天看了下Spring的Configuration即java类配置bean,这个spring3的新功能虽然现在已经spring5了但是这种配置bean的方式也是比较火的 做了如下测试发现一个现象先说这个现象后面用自己的理解再简单实现一下。
先说现象
在java配置类中加Configuration下面的声明bean的方法就只会被调一次也就是初始化的时候哪怕是下面的方法直接互相引用返回的new的对象的构造方法也只会调一次 而如果不加Configuration那么下面的方法如果有相互调用那么返回的new的对象的构造方法就会被调多次 下面是测试代码
Configuration
ComponentScan(com.zs.cglib)
//这个类作为配置类
public class CglibConfig {Beanpublic TestDomain testDomain(){return new TestDomain();}Beanpublic TestDomainTwo testDomainTwo(){//这个方法会预先调用上一个方法testDomain();return new TestDomainTwo();}
}Component(testDomain)
public class TestDomain {public TestDomain() {//构造参数打印证明被调过System.out.println(new TestDomain-------------);}
}Component(testDomainTwo)
public class TestDomainTwo {public TestDomainTwo() {//构造参数打印证明被调过System.out.println(new TestDomainTwo-------------);}
}public class StartMain {//启动测试public static void main(String[] args) {AnnotationConfigApplicationContext anno new AnnotationConfigApplicationContext(CglibConfig.class);System.out.println(anno.getBean(TestDomain.class));System.out.println(anno.getBean(TestDomainTwo.class));}
}可以发现如果CglibConfig加上Configuration就会打印出 new TestDomain------------- new TestDomainTwo------------- 如果把Configuration去掉就会打印出 new TestDomain------------- new TestDomain------------- new TestDomainTwo------------- 也就是说加上Configurationnew出TestDomain实例只执行了一次也就是说testDomainTwo()中调用的testDomain()并没有new出新的TestDomain实例。 而把Configuration去掉TestDomain实例就会被new两次也就是testDomainTwo()中调用的testDomain()也有new出TestDomain实例。
这是为什么呢当然肯定和Configuration有关。
一般情况我们把带有Configuration的类叫做全注解配置类也叫Full配置类 我们把不带Configuration的类叫Lite配置类
源码解释
追了下源码一直找到org.springframework.context.annotation.ConfigurationClassPostProcessor#enhanceConfigurationClasses 突然看到enhancer这不是cglib的东西么根据这个线索再追就知道了加上Configuration其实是用了Cglib代理了 所以方法已经被增强了那肯定还有其他逻辑 再找到org.springframework.context.annotation.ConfigurationClassEnhancer#newEnhancer 这就是cglib了那就找callback再找intercept方法org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor#intercept 这个方法里面增强了原方法其实就是用map实现的下面来个简单的模仿
根据cglib实现简单的效果
亲自写了个简单的cglib实现还原了Configuration的这种现象 测试代码如下
CglibConfig这个类把注解都去掉咱们自己实现这个只调一次的功能
public class CglibConfig {public TestDomain testDomain(){return new TestDomain();}public TestDomainTwo testDomainTwo(){testDomain();return new TestDomainTwo();}
}
TestDomain和TestDomainTwo两个类不变
新增一个callback实现以下逻辑。这都是cglib的知识点不动可以查下cglib简单实现
public class MyCallBack implements MethodInterceptor {//这个map就记录了方法每次调用的痕迹并把调用后的结果保存起来不是第一次调用的话就直接将结果返回就行了private static MapString,Object map new HashMap();Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//获取方法名字String name method.getName();if(isFirst(name)){//如果方法是第一次调用Object invoke methodProxy.invokeSuper(o, objects);//调用完将结果保存在map中map.put(name,invoke);return invoke;}else{//第二次第三次调用就走这里直接返回map中的结果return map.get(name);}}private boolean isFirst(String name) {//判断是不是第一次调用其实就是看这个name在map中是不是已经注册了Object invoke map.get(name);if(invoke null){return true;}return false;}
}
再写个cglib的util,以便main方法调用
public class CglibUtil {public static Object getBean(){//看到这个应该就要想到cglibEnhancer enhancer new Enhancer();enhancer.setSuperclass(CglibConfig.class);enhancer.setCallback(new MyCallBack());CglibConfig proxy (CglibConfig) enhancer.create();return proxy;}
}
//主方法测试
public class StartMain {public static void main(String[] args) {CglibConfig bean (CglibConfig) CglibUtil.getBean();bean.testDomain();bean.testDomainTwo();}
}执行的结果是 new TestDomain------------- new TestDomainTwo-------------
总结
利用cglib代理增强 如果这个方法第一次调用就把调用的方法名和返回的结果保存在map中 后面再有调用就直接返回结果了不会真正再去执行了
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/89601.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!