`
357029540
  • 浏览: 735003 次
  • 性别: 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 框架中,动态加载 bean 是一个非常实用的功能,特别是在我们需要在不改变原有程序结构的基础上添加新的 bean 的时候。通过使用 Spring 的 ...

    Spring动态加载配置文件

    下面将详细阐述如何实现Spring动态加载配置文件的热部署方案。 首先,配置文件路径的固定是基础。通常,我们将Spring的配置文件(如`applicationContext.xml`)放在项目的类路径下,如`src/main/resources`目录。...

    spring运行过程中动态注册bean

    在Spring框架中,动态注册Bean是一项非常实用的功能,它允许我们在应用运行时向Spring容器添加新的Bean定义。这种能力在很多场景下都是极其有用的,比如根据不同的环境配置加载不同的服务实现,或者在运行时根据某些...

    Spring Bean 加载顺序 .

    对于Singleton Bean,Spring在容器关闭时会调用`@PreDestroy`注解的方法和实现DisposableBean接口的`destroy()`方法。对于Prototype作用域的Bean,Spring不会自动管理销毁,需要由用户负责。 在实际应用中,理解...

    spring的bean加载顺序样例项目

    - 如果Bean配置了AOP代理,如`@AspectJ`切面或基于接口的代理,那么在Bean实例化后,Spring会创建代理对象,代理对象负责拦截方法调用并执行相关的切面逻辑。 6. **Bean的销毁** - 对于单例Bean,Spring容器在...

    Spring動態加載Bean

    本篇文章将深入探讨Spring动态加载Bean的概念、实现方式以及其在实际开发中的应用。 首先,理解Bean的生命周期是至关重要的。在Spring中,Bean的生命周期包括实例化、初始化、正常服务和销毁等阶段。通常,Spring...

    spring IOC反射装载bean

    这个Demo有助于理解Spring如何通过反射机制加载和管理Bean,以及如何通过XML配置实现依赖注入。 总的来说,"spring IOC反射装载bean"是Spring框架的基础,它使得开发者可以专注于业务逻辑,而不必关心对象的创建和...

    Spring Bean创建初始化流程.docx

    `createBean(beanName, mbd, args)`在`AbstractAutowireCapableBeanFactory`中实现,它负责根据Bean定义创建Bean实例。 8. **实际创建Bean**: 在`doCreateBean()`方法中,Spring会创建Bean的实例,`...

    详解Spring 中如何控制2个bean中的初始化顺序

    因此,在使用 DependsOn 注解时,需要了解 Spring 中 bean 的加载过程,以免出现错误。 其他实现方式 除了上述两种方式外,还有其他方式可以控制 2 个 bean 的初始化顺序。例如,可以使用 Spring 的 @Order 注解来...

    普通类调用Spring bean对象

    在非Spring环境中的类(普通类)想要调用Spring bean,我们需要利用Spring提供的API或工具来实现这个过程。 1. **ApplicationContext**:这是Spring提供的一个接口,代表了Spring的上下文,包含了bean的定义和bean...

    spring bean XML配置入门

    一旦XML配置加载到Spring容器中,容器将根据配置创建Bean实例,并按照定义进行初始化、依赖注入,最后完成Bean的生命周期管理。 10. **实践操作**: 在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean...

    Spring中与Bean相关的接口

    例如,当使用`XmlBeanFactory`从XML配置文件加载Bean定义时,`BeanFactory`会解析并加载配置,但不会立即创建Bean。 接着,`ApplicationContext`是`BeanFactory`的一个扩展,它添加了更多企业级功能,如消息支持、...

    Spring中Bean的生命周期 applicationcontext的应用(实现国际化,事件的传递)

    1. **初始化**:当Spring容器加载Bean定义时,它会创建Bean的实例。这通常通过无参构造函数完成。如果Bean定义中包含了工厂方法,那么会使用该方法来创建Bean。 2. **属性注入**:接着,Spring会根据Bean定义中的...

    spring bean的生命周期

    - **Singleton Beans的懒加载**:如果Bean的scope为singleton,并且在XML配置中没有设置`lazy-init="true"`,那么Spring容器在启动时就会实例化这些Bean。 - **Prototype Beans的每次请求创建**:scope为prototype...

    Spring IoC加载流程讲解

    Spring IoC 加载流程讲解 在本节中,我们将对 Spring IoC 加载流程进行详细的讲解,并探讨 IoC 思想和依赖倒置原则的应用。 IoC 控制反转 IoC(Inversion of Control)是指在软件设计中,将对象实例的控制权从...

    深度解析spring容器管理bean

    这里,Spring会通过反射机制加载UserService类,并根据`&lt;property&gt;`标签设置属性值,实现依赖注入。`ref="dataSource"`表明userService Bean依赖于名为dataSource的另一个Bean。 反射机制是Java提供的一种能够在...

    spring bean加载

    在Spring框架中,Bean加载是核心功能之一,它关乎到整个应用的生命周期管理和依赖注入。Spring通过XML配置、注解配置或Java配置三种方式来定义Bean,并进行加载。接下来,我们将详细探讨Spring Bean加载的过程及其...

    Spring管理的Bean的生命周期

    当Spring容器加载了配置文件(如XML或Java配置)后,它会根据配置信息实例化Bean。Bean的创建有两种方式:默认构造器创建和工厂方法创建。默认构造器创建是通过无参数构造函数实例化Bean,而工厂方法则是通过指定的...

    Spring Bean重复执行两次(实例被构造两次)问题分析

    在Spring容器初始化时,它会根据配置加载Bean的定义,并根据需要创建Bean实例。Bean的生命周期大致分为以下几个阶段:构造、初始化、正常使用、销毁。如果一个Bean被创建了两次,那么可能是在构造或初始化阶段出现了...

Global site tag (gtag.js) - Google Analytics