Spring calls the implementation after dynamically loading the bean

        In the process of using Spring, we sometimes do not want to inject beans through xml, and hope to add the beans we need without changing the original program structure. At this time, we can use Spring's spring-beans The BeanFactoryPostProcessor interface class provided in the jar package, by implementing this interface class, we can dynamically load the required beans, especially when the program that has been packaged in the jar is introduced and there is no way to make changes, this interface is We provide extremely convenient entrance.

      Because I tested this interface on the basis of other projects, the introduced jar has its particularity, so students who need to refer to it can implement it according to their own needs.

     1. Introduce springboot through pom.xml:

      

<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. Create the App.java startup class:

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. Create a DynamicCreateBean.java as a dynamically loaded object:

public class DynamicCreateBean {

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

}

       4. Add another project outside this project and import it into the project in the form of jar for testing dynamic loading. The new project in my project is threadTest.jar, which is a package for multi-threaded testing. class, the students who need it can create a new one by themselves to make a jar package for testing.

      5. Add a LoadBean.java class for dynamically loading beans:

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");
        //Used to set other beans that need to be introduced in the specified class
        //beanDefinitionBuilder.addPropertyValue("otherBeanName","otherBeanName");
        this.defaultListableBeanFactory.registerBeanDefinition("dynamicCreateBean",beanDefinitionBuilder.getBeanDefinition());

        beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Run.class.getName());
        //Used to set other beans that need to be introduced in the specified class
        //beanDefinitionBuilder.addPropertyValue("otherBeanName","otherBeanName");
        this.defaultListableBeanFactory.registerBeanDefinition("mulitRun",beanDefinitionBuilder.getBeanDefinition());
    }
}

      6. Create a test class:

      

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

     The above is the entire dynamic loading process. If you need to know more, you can continue to find information on the Internet.

2017-8-30 Newly added

     Recently, I found another way to inject dynamic beans when I was reading related articles on spring cloud Feign. The code inside is provided in the FeignClientsRegistrar.java class. The specific code is:

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 = qualify;
        }

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

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327018945&siteId=291194637