package com.kangaroohy.milo.configuration; import com.kangaroohy.milo.pool.MiloConnectFactory; import com.kangaroohy.milo.pool.MiloConnectPool; import com.kangaroohy.milo.service.MiloService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; import org.eclipse.milo.opcua.sdk.client.OpcUaClient; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import javax.annotation.PreDestroy; /** * @author mes * @date 2020/4/25 * @desc milo-spring-boot-starter * @since 0.0.1 */ @Configuration @EnableConfigurationProperties(MiloProperties.class) @ConditionalOnClass({MiloService.class, MiloConnectPool.class}) @ConditionalOnProperty(prefix = MiloProperties.PREFIX, value = "enabled", havingValue = "true", matchIfMissing = true) @Slf4j public class MiloAutoConfiguration { private final MiloProperties properties; private MiloConnectPool connectPool; public MiloAutoConfiguration(MiloProperties properties) { this.properties = properties; } @Bean(name = "miloConnectPool") @ConditionalOnMissingBean({MiloConnectPool.class}) protected MiloConnectPool miloConnectPool() { MiloConnectFactory objectFactory = new MiloConnectFactory(this.properties); //设置对象池的相关参数 GenericKeyedObjectPoolConfig poolConfig = new GenericKeyedObjectPoolConfig<>(); MiloProperties.Pool pool = properties.getPool(); // 最大空闲数 poolConfig.setMaxIdlePerKey(pool.getMaxIdle()); //最小空闲,设置为2表示池内至少存放2个空闲对象(当池内有2个空闲对象时调用borrowObject去对象时会立即调用创建对象的方法保证池内有2个空闲对象) poolConfig.setMinIdlePerKey(pool.getMinIdle()); //最大总数 10 poolConfig.setMaxTotal(pool.getMaxTotal()); // 多久执行一次对象扫描,将无用的对象销毁,默认-1不扫描 // poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1)); // 在获取对象的时候检查有效性, 默认false poolConfig.setTestOnBorrow(true); // 在归还对象的时候检查有效性, 默认false poolConfig.setTestOnReturn(false); // 在空闲时检查有效性, 默认false poolConfig.setTestWhileIdle(false); // 最大等待时间, 默认的值为-1,表示无限等待。 // poolConfig.setMaxWait(Duration.ofSeconds(1)); // 是否启用后进先出, 默认true poolConfig.setLifo(true); // 连接耗尽时是否阻塞, false立即抛异常,true阻塞直到超时, 默认true poolConfig.setBlockWhenExhausted(true); // 每次逐出检查时 逐出的最大数目 默认3 poolConfig.setNumTestsPerEvictionRun(3); //一定要关闭jmx,不然springboot启动会报已经注册了某个jmx的错误 poolConfig.setJmxEnabled(false); //新建一个对象池,传入对象工厂和配置 connectPool = new MiloConnectPool(objectFactory, poolConfig); initPool(pool.getInitialSize(), pool.getMaxIdle()); return connectPool; } @Bean @ConditionalOnMissingBean(MiloService.class) @DependsOn("miloConnectPool") public MiloService miloService(MiloConnectPool miloConnectPool) { return new MiloService(miloConnectPool, properties); } /** * 预先加载testObject对象到对象池中 * * @param initialSize 初始化连接数 * @param maxIdle 最大空闲连接数 */ private void initPool(int initialSize, int maxIdle) { if (initialSize <= 0) { return; } properties.getConfig().forEach((key, config) -> { for (int i = 0; i < Math.min(initialSize, maxIdle); i++) { try { connectPool.addObject(config); } catch (Exception e) { throw new RuntimeException(e); } } }); } @PreDestroy public void destroy() { if (connectPool != null) { connectPool.close(); log.info("all opcUaClients are closed"); } } }