`
357029540
  • 浏览: 727806 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

Spring动态加载bean后调用实现

阅读更多

        在使用Spring的过程中,我们有时候并不想通过xml的方式进行bean的注入,希望在不改变原有的程序结构的基础上添加我们需要的bean,这个时候我们可以利用Spring的spring-beans的jar包里提供的BeanFactoryPostProcessor接口类,通过实现这个接口类,我们可以动态的加载所需要的bean,特别是在引入已经打包在jar里面的程序而没有办法做出修改的情况下,这个接口就为我们提供了及其方便的入口。

      因为我是在其他项目的基础上测试的这个接口,所以引入的jar有其特殊性,所以需要参考的同学可以按照自己的需求来实现。

     1.通过pom.xml来引入springboot:

      

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.thread</groupId>
            <artifactId>test</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>f:/threadTest.jar</systemPath>
        </dependency>
    </dependencies>

 

    2.创建App.java启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author liaoyubo
 * @version 1.0 2017/7/31
 * @description
 */
@SpringBootApplication
public class App {

    public static void main(String [] args){
        SpringApplication.run(App.class);
    }

}

       3.创建一个DynamicCreateBean.java来作为动态加载的对象:

public class DynamicCreateBean {

    public void printMethod(){
        System.out.println("DynamicCreateBean Success");
    }

}

       4.在本项目外另外新增一个项目打成jar的形式导入到该项目中用于测试动态加载,在我的项目中新增的是threadTest.jar,该包是一个用于多线程测试的类,需要的同学自己随便新建一个来打成jar包测试即可。

      5.新增一个LoadBean.java类用于动态加载bean:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Component;

import com.thread.mulitSynThreadTest.Run;
/**
 * @author liaoyubo
 * @version 1.0 2017/8/11
 * @description
 */
@Component
public class LoadBean implements BeanFactoryPostProcessor {

    private DefaultListableBeanFactory defaultListableBeanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        this.defaultListableBeanFactory = (DefaultListableBeanFactory)configurableListableBeanFactory;

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.springRedis.dynamic.DynamicCreateBean");
        //用于设置指定的类中需要引入的其他bean
        //beanDefinitionBuilder.addPropertyValue("otherBeanName","otherBeanName");
        this.defaultListableBeanFactory.registerBeanDefinition("dynamicCreateBean",beanDefinitionBuilder.getBeanDefinition());

        beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Run.class.getName());
        //用于设置指定的类中需要引入的其他bean
        //beanDefinitionBuilder.addPropertyValue("otherBeanName","otherBeanName");
        this.defaultListableBeanFactory.registerBeanDefinition("mulitRun",beanDefinitionBuilder.getBeanDefinition());
    }
}

      6.创建测试类:

      

import com.springRedis.App;
import com.springRedis.dynamic.DynamicCreateBean;
import com.thread.mulitSynThreadTest.Run;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;



/**
 * @author liaoyubo
 * @version 1.0 2017/8/11
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class MultiTest {

    @Autowired
    private DynamicCreateBean dynamicCreateBean;

    @Autowired
    private Run run;

    @Test
    public void testDynamic(){
        dynamicCreateBean.printMethod();
        run.printRun();
    }
}

     以上就是整个的动态加载过程,如果需要了解更多,可以在网上继续查找资料。

2017-8-30新添加

     最近在看spring cloud Feign相关文章时发现了另外一种注入动态bean的方式,里面的代码提供是在FeignClientsRegistrar.java类中,具体代码为:

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
        String className = annotationMetadata.getClassName();
        BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
        this.validate(attributes);
        definition.addPropertyValue("url", this.getUrl(attributes));
        definition.addPropertyValue("path", this.getPath(attributes));
        String name = this.getName(attributes);
        definition.addPropertyValue("name", name);
        definition.addPropertyValue("type", className);
        definition.addPropertyValue("decode404", attributes.get("decode404"));
        definition.addPropertyValue("fallback", attributes.get("fallback"));
        definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
        definition.setAutowireMode(2);
        String alias = name + "FeignClient";
        AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
        boolean primary = ((Boolean)attributes.get("primary")).booleanValue();
        beanDefinition.setPrimary(primary);
        String qualifier = this.getQualifier(attributes);
        if(StringUtils.hasText(qualifier)) {
            alias = qualifier;
        }

        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
    }

 

分享到:
评论

相关推荐

    Spring动态加载bean后调用实现方法解析

    主要介绍了Spring动态加载bean后调用实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    尚硅谷]_佟刚_Spring IOC 容器中 Bean 的生命周期.pdf

    3、import用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“config1.xml”, config2.xml})传给ApplicationContext实现进行加载多个配置文件,...

    关于mybatis spring与dubbo是怎么通过一个接口 你就能调用到一个bean方法的讲解

    Mybatis 或者 dubbo 或者 ...首先要弄清楚 spring的加载与生成bean的机制 spring在启动的时候 会 扫描 所有定义的 bean的类 并定义BeanDefinition 然后通过BeanDefinition 在调用creataBean方法的时候会 去实例 初始

    高级开发spring面试题和答案.pdf

    SPI 机制(Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制), 很多地方有用到: AOP Spring的AOP的底层实现原理; 为什么jdk动态代理是必须是接口 两种动态代理的区别 AOP实现方式:...

    spring jar 包详解

    (2) spring-beans.jar 这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI支持,...

    从零开始学Spring Boot

    1.20 Spring Boot普通类调用bean 1.21 使用模板(thymeleaf-freemarker) 1.22 Spring Boot 添加JSP支持 1.23 Spring Boot Servlet 1.24 Spring Boot过滤器、监听器 1.25 Spring Boot 拦截器HandlerInterceptor 1.26...

    Spring入门.docx

    (1)DI注入属性:name为set方法去掉set之后首字母小写,ref为bean的id,需要有set方法,Spring会自动调用进行注入 (2)BeanFactory与ApplicationContext: ApplicationContext内部封装了BeanFactory,功能更加强大...

    Spring中文帮助文档

    6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入...

    Spring攻略(第二版 中文高清版).part1

    2.11 创建Bean后处理器 85 2.11.1 问题 85 2.11.2 解决方案 85 2.11.3 工作原理 86 2.12 外部化Bean配置 89 2.12.1 问题 89 2.12.2 解决方案 89 2.12.3 工作原理 90 2.13 解析文本消息 91 2.13.1...

    Spring API

    6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入...

    浅谈 Spring 原理 透析,ioc aop

    * 接口注入:通过定义某一类型的接口 interface 来标识一组功能相似的对象,并在这一组对象与其调用者间,在编译时分离,在运行时才动态加载实现类。这种方式使得调用者和组件对象间的依赖程度减小,提高了模块的...

    Spring.3.x企业应用开发实战(完整版).part2

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    Spring.html

    BeanFactory:使用这个工厂创建对象的方式都是懒加载,在调用的时候再创建 ClassPathXmlApplicationContext:使用这个工厂创建对象,他会根据scope智能判断是否懒加载,如果是单例则创建容器时就会创建里面bean的实例,...

    Spring攻略(第二版 中文高清版).part2

    2.11 创建Bean后处理器 85 2.11.1 问题 85 2.11.2 解决方案 85 2.11.3 工作原理 86 2.12 外部化Bean配置 89 2.12.1 问题 89 2.12.2 解决方案 89 2.12.3 工作原理 90 2.13 解析文本消息 91 2.13.1...

    spring.xls

    spring的IOC: ... * 由spring容器调用init方法 * 在构造函数之后执行 * 销毁 * 如果是单例,则必须返回ClassPathXmlApplicationContext该容器,才能执行销毁工作 * 如果是多例,容器不负责销毁

    Spring面试题

    在 XML 文件中定义的 Bean 是被消极加载的,这意味在需要 bean 之前,bean 本身不会被初始化。要从 BeanFactory 检索 bean,只需调用 getBean() 方法,传入将要检索的 bean 的名称即可,如清单 2 所示。 清单 2. ...

    spring security 参考手册中文版

    29.4.5 Spring Bean配置 226 29.4.6 LDAP属性和定制的UserDetails 227 29.5 Active Directory认证 228 29.5.1 ActiveDirectoryLdapAuthenticationProvider 228 活动目录错误代码 229 30. JSP标签库 230 30.1声明...

    Spring3.x企业应用开发实战(完整版) part1

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    spring boot源码

    3. 在开始刷新之前,bean定义被加载之后发送 ApplicationPreparedEvent。 4. 在上下文刷新之后且所有的应用和命令行运行器被调用之前发送 ApplicationStartedEvent。 5. 在应用程序和命令行运行

    学习SSM源码分析的一次实践,自己实现SSM框架

    **首先介绍下这次的总体思路:** 在spring中最核心的就是IOC容器,默认采用的是通过单例的模式来进行管理我们注入到Ioc中的bean...并且通过动态注入的方式进行 接口的调用,并且实现对应的调用对应xml中的sql片段。

Global site tag (gtag.js) - Google Analytics