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

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

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

  2021-04-03 我要评论

前言

在使用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(); 
 } 
} 

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

最近在看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); 
 } 
您可能感兴趣的文章:

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们