阅读对象##

搭框架人员,或者其他感兴趣的开发人员

背景##

一般来说在业务代码中,加上 @Component, @Service@Repository, @Controller等注解就可以实现将bean注册到Spring中了。

但是在写框架,可能有些类会动态生成,怎么动态注册到Spring中呢?

BeanDefinitionRegistryPostProcessor 接口##

BeanDefinitionRegistryPostProcessor接口是一个可以修改spring工厂中已定义的bean的接口,该接口有个postProcessBeanDefinitionRegistry方法。

/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* [@param](https://my.oschina.net/u/2303379) registry the bean definition registry used by the application context
* [@throws](https://my.oschina.net/throws) org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

实现##

代码###

public class App implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition("demoEntityDao", getDefinition(AcAlert.class));
}
private BeanDefinition getDefinition(Class<?> cls) {
DaoInterfaceGenerator g = new DaoInterfaceGenerator(cls);
Class<?> daoClass = g.generateClass();
GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setBeanClass(MapperFactoryBean.class);
bd.getConstructorArgumentValues().addGenericArgumentValue(daoClass);
bd.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference("sqlSessionFactory")); return bd;
}
}

步骤说明###

  1. 实现BeanDefinitionRegistryPostProcessor接口
  2. 处理postProcessBeanDefinitionRegistry方法
  3. 生成BeanDefinition,上面展示了动态添加一个mybatis Dao的bean注册过程

我遇到的坑##

当动态生成生成mybatis的dao接口时,报这个错误:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoEntityDao': Post-processing of FactoryBean's singleton object failed; nested exception is java.lang.IllegalArgumentException: interface com.dhcc.ac.domain.AcAlertDao is not visible from class loader
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1590)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1054)
at com.dhcc.framework.App.main(App.java:48)
Caused by: java.lang.IllegalArgumentException: interface com.dhcc.ac.domain.AcAlertDao is not visible from class loader
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:581)
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557)
at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230)
at java.lang.reflect.WeakCache.get(WeakCache.java:127)
at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719)
at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:121)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor.postProcessAfterInitialization(AbstractAdvisingBeanPostProcessor.java:90)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1723)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113)
... 5 more

错误原因在于动态生成的class加载的classloader,与Proxy.newProxyInstance使用的ClassLoader,不是同一个classloader,所以在Proxy.newProxyInstance找不到这个新生成的类。

解决办法###

动态加载类,一般都是用defineClass动态加载到ClassLoader里去。

但defineClass不是public,所以在这里卡了一段时间。

后来,突然之间找到了解决办法,使用反射调用defineClass就好了呀。

小结##

技术没什么高深的,我后面将要写的一个功能,用到了本篇的技术,这里先介绍一下。


我的微信zouhaibin294148,不知不觉写了10多年代码了

如何动态在spring mvc中增加bean的更多相关文章

  1. Spring mvc 中使用 kaptcha 验证码

    生成验证码的方式有很多,个人认为较为灵活方便的是Kaptcha ,他是基于SimpleCaptcha的开源项目.使用Kaptcha 生成验证码十分简单并且参数可以进行自定义.只需添加jar包配置下就可 ...

  2. 7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;

    7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...

  3. Spring MVC 中的http Caching

    文章目录 过期时间 Last-Modified ETag Spring ETag filter Spring MVC 中的http Caching Cache 是HTTP协议中的一个非常重要的功能,使 ...

  4. spring mvc中使用freemark的一点心得

    参考文档: FreeMarker标签与使用 连接http://blog.csdn.net/nengyu/article/details/6829244 freemarker学习笔记--指令参考: ht ...

  5. Spring MVC中处理静态资源的多种方法

    处理静态资源,我想这可能是框架搭建完成之后Web开发的”头等大事“了. 因为一个网站的显示肯定会依赖各种资源:脚本.图片等,那么问题来了,如何在页面中请求这些静态资源呢? 还记得Spring MVC中 ...

  6. 解决spring配置中的bean类型的问题:BeanNotOfRequiredTypeException

    解决spring配置中的bean类型的问题:BeanNotOfRequiredTypeException这个问题出现的原因:一般在使用annotation的方式注入spring的bean 出现的,具体 ...

  7. Spring MVC 中的基于注解的 Controller【转】

    原文地址:http://my.oschina.net/abian/blog/128028 终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 H ...

  8. spring mvc中的文件上传

    使用commons-fileupload上传文件所需要的架包有:commons-fileupload 和common-io两个架包支持,可以到Apache官网下砸. 在配置文件spring-mvc.x ...

  9. spring mvc中的valid

    当你希望在spring mvc中直接校验表单参数时,你可以采用如下操作: 声明Validator的方式: 1.为每一个Controller声明一个Validator @Controller publi ...

随机推荐

  1. vcpu

    qemu_kvm_start_vcpu --> qemu_init_vcpu --> x86_cpu_realizefn -->  x86_cpu_common_class_init ...

  2. 基于jQuery的Validate表单验证

    表单验证可以说在前端开发工作中是无处不在的~ 有数据,有登录,有表单, 都需要前端验证~~  而我工作中用到最多的就是基于基于jQuery的Validate表单验证~  就向下面这样~ 因为今天有个朋 ...

  3. 关于MapReduce中自定义分区类(四)

    MapTask类 在MapTask类中找到run函数 if(useNewApi){       runNewMapper(job, splitMetaInfo, umbilical, reporter ...

  4. Json在PHP与JS之间传输

    1. JS-->PHP a). JS create Json <script> $(document).ready(function(){ /*--JS create Json--* ...

  5. Bestcoder#5 1002

    Bestcoder#5 1002 Poor MitsuiTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  6. spring data jpa分页

    controller层 @RequestMapping(value="/search") @ResponseBody public String search(HttpServle ...

  7. 第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)

    在开头也是先给大家道个歉,由于最近准备婚事导致这篇文章耽误了许久,同时也谢谢老婆大人对我的支持. 回顾上篇文章,我们重造了一个controller,这个controller中用到了视图引擎,我们的视图 ...

  8. 关于robotframework,app,appium的xpath定位问题及常用方法

    关于类似的帖子好像很多,但是没有找到具体能帮我解决问题的办法.还是自己深究了好久才基本知道app上面的xpath定位和web上的不同点: 先放一个图: A,先说说不用xpath的场景,一般是用于存在i ...

  9. UML类图符号 各种关系说明以及举例

    UML中描述对象和类之间相互关系的方式包括:依赖,关联,聚合,组合,泛化,实现等. 表示关系的强弱:组合>聚合>关联>依赖 相互间关系 聚合是表明对象之间的整体与部分关系的关联,而组 ...

  10. 原生JavaScript实现Ajax

    var getXmlHttpRequest = function() { if (window.XMLHttpRequest) { //主流浏览器提供了XMLHttpRequest对象 return ...