SpringBoot代码方式注册Bean

写JavaFX时需要动态切换数据源,因此产生这个需求。

工具类,用于在代码中获取spring的上下文:

@Component
public class Spring implements ApplicationContextAware {

    public static AnnotationConfigApplicationContext APP;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(Spring.APP == null) {
            Spring.APP = (AnnotationConfigApplicationContext) applicationContext;
        }
    }

}

下面这个类展示如何实现代码方式注册Bean:

package com.abc.gen.service;

import com.abc.gen.util.Spring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.sql.SQLRecoverableException;

/**
 * create by: CaiBaoHong
 * create date: 2018/2/2 0002
 */
@Component
public class DatabaseService {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final String JDBC_TEMPLATE_BEAN = "jdbcTemplate";

    /**
     * 每次调用此方法,都会新创建一个JdbcTemplate并注入到Spring上下文中
     * @param host
     * @param port
     * @param username
     * @param password
     * @return
     * @throws SQLException
     */
    public JdbcTemplate newJdbcTemplate(String host, String port, String username, String password) throws SQLException {

        //创建一个新的JdbcTemplate
        DataSource dataSource = DataSourceBuilder.create()
                .driverClassName("com.mysql.jdbc.Driver")
                .url("jdbc:mysql://" + host + ":" + port + "?useUnicode=true&characterEncoding=utf-8&useSSL=false")
                .username(username)
                .password(password)
                .build();
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        //判断
        if (Spring.APP.containsBeanDefinition(JDBC_TEMPLATE_BEAN)){
            //如果Spring上下文已存在Bean,先删除
            Spring.APP.removeBeanDefinition(JDBC_TEMPLATE_BEAN);
        }else{
            //如果不存在,创建
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JdbcTemplate.class);
            Spring.APP.registerBeanDefinition(JDBC_TEMPLATE_BEAN,builder.getBeanDefinition());
        }

        //注入JdbcTemplate实例
        Spring.APP.getBeanFactory().registerSingleton(JDBC_TEMPLATE_BEAN,jdbcTemplate);

        //打印测试:
        logger.info("set dataSource : "+dataSource);
        logger.info("set jdbcTemplate : "+jdbcTemplate);
        logger.info("set jdbcTemplate.dataSource : "+jdbcTemplate.getDataSource());
        return jdbcTemplate;
    }

}

调用DatabaseService的类中可以拿到动态注入的JdbcTemplate:

@Component
public class RootLayoutController {

    @Autowired
    private DatabaseService databaseService;

    @Lazy
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 用户点击“连接”
     * @throws SQLException
     */
    @FXML
    private void handleConfirmConnection() throws SQLException {
        String host = hostField.getText();
        String port = portField.getText();
        String username = usernameField.getText();
        String password = passwordField.getText();
        //检查连接参数
        String connParamsError = checkService.checkConnectionParams(host, port, username, password);
        if (connParamsError!=null){
            alertService.error(connParamsError);
            return ;
        }
        //初始化Datasource和JdbcTemplate
        databaseService.newJdbcTemplate(host, port, username, password);
        //尝试连接
        try {
            jdbcTemplate.getDataSource().getConnection();
        } catch (SQLException e) {
            alertService.error("连接失败:"+e.getMessage());
            return;
        }
        alertService.info("连接成功!");
    }

    @FXML
    private void handleTest(){
        System.out.println("jdbcTemplate : "+jdbcTemplate);
    }


    
}

你可能感兴趣的:(springboot,javafx)