在使用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 是一个非常实用的功能,特别是在我们需要在不改变原有程序结构的基础上添加新的 bean 的时候。通过使用 Spring 的 ...
下面将详细阐述如何实现Spring动态加载配置文件的热部署方案。 首先,配置文件路径的固定是基础。通常,我们将Spring的配置文件(如`applicationContext.xml`)放在项目的类路径下,如`src/main/resources`目录。...
在Spring框架中,动态注册Bean是一项非常实用的功能,它允许我们在应用运行时向Spring容器添加新的Bean定义。这种能力在很多场景下都是极其有用的,比如根据不同的环境配置加载不同的服务实现,或者在运行时根据某些...
对于Singleton Bean,Spring在容器关闭时会调用`@PreDestroy`注解的方法和实现DisposableBean接口的`destroy()`方法。对于Prototype作用域的Bean,Spring不会自动管理销毁,需要由用户负责。 在实际应用中,理解...
- 如果Bean配置了AOP代理,如`@AspectJ`切面或基于接口的代理,那么在Bean实例化后,Spring会创建代理对象,代理对象负责拦截方法调用并执行相关的切面逻辑。 6. **Bean的销毁** - 对于单例Bean,Spring容器在...
本篇文章将深入探讨Spring动态加载Bean的概念、实现方式以及其在实际开发中的应用。 首先,理解Bean的生命周期是至关重要的。在Spring中,Bean的生命周期包括实例化、初始化、正常服务和销毁等阶段。通常,Spring...
这个Demo有助于理解Spring如何通过反射机制加载和管理Bean,以及如何通过XML配置实现依赖注入。 总的来说,"spring IOC反射装载bean"是Spring框架的基础,它使得开发者可以专注于业务逻辑,而不必关心对象的创建和...
`createBean(beanName, mbd, args)`在`AbstractAutowireCapableBeanFactory`中实现,它负责根据Bean定义创建Bean实例。 8. **实际创建Bean**: 在`doCreateBean()`方法中,Spring会创建Bean的实例,`...
因此,在使用 DependsOn 注解时,需要了解 Spring 中 bean 的加载过程,以免出现错误。 其他实现方式 除了上述两种方式外,还有其他方式可以控制 2 个 bean 的初始化顺序。例如,可以使用 Spring 的 @Order 注解来...
在非Spring环境中的类(普通类)想要调用Spring bean,我们需要利用Spring提供的API或工具来实现这个过程。 1. **ApplicationContext**:这是Spring提供的一个接口,代表了Spring的上下文,包含了bean的定义和bean...
一旦XML配置加载到Spring容器中,容器将根据配置创建Bean实例,并按照定义进行初始化、依赖注入,最后完成Bean的生命周期管理。 10. **实践操作**: 在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean...
例如,当使用`XmlBeanFactory`从XML配置文件加载Bean定义时,`BeanFactory`会解析并加载配置,但不会立即创建Bean。 接着,`ApplicationContext`是`BeanFactory`的一个扩展,它添加了更多企业级功能,如消息支持、...
1. **初始化**:当Spring容器加载Bean定义时,它会创建Bean的实例。这通常通过无参构造函数完成。如果Bean定义中包含了工厂方法,那么会使用该方法来创建Bean。 2. **属性注入**:接着,Spring会根据Bean定义中的...
- **Singleton Beans的懒加载**:如果Bean的scope为singleton,并且在XML配置中没有设置`lazy-init="true"`,那么Spring容器在启动时就会实例化这些Bean。 - **Prototype Beans的每次请求创建**:scope为prototype...
Spring IoC 加载流程讲解 在本节中,我们将对 Spring IoC 加载流程进行详细的讲解,并探讨 IoC 思想和依赖倒置原则的应用。 IoC 控制反转 IoC(Inversion of Control)是指在软件设计中,将对象实例的控制权从...
这里,Spring会通过反射机制加载UserService类,并根据`<property>`标签设置属性值,实现依赖注入。`ref="dataSource"`表明userService Bean依赖于名为dataSource的另一个Bean。 反射机制是Java提供的一种能够在...
在Spring框架中,Bean加载是核心功能之一,它关乎到整个应用的生命周期管理和依赖注入。Spring通过XML配置、注解配置或Java配置三种方式来定义Bean,并进行加载。接下来,我们将详细探讨Spring Bean加载的过程及其...
当Spring容器加载了配置文件(如XML或Java配置)后,它会根据配置信息实例化Bean。Bean的创建有两种方式:默认构造器创建和工厂方法创建。默认构造器创建是通过无参数构造函数实例化Bean,而工厂方法则是通过指定的...
在Spring容器初始化时,它会根据配置加载Bean的定义,并根据需要创建Bean实例。Bean的生命周期大致分为以下几个阶段:构造、初始化、正常使用、销毁。如果一个Bean被创建了两次,那么可能是在构造或初始化阶段出现了...