Spring Boot 集成
本文档详细介绍如何在 Spring Boot 应用中集成 LCGYL Framework。
快速开始
添加依赖
gradle
dependencies {
implementation 'com.lcgyl:lcgyl-framework-spring:${version}'
}xml
<dependency>
<groupId>com.lcgyl</groupId>
<artifactId>lcgyl-framework-spring</artifactId>
<version>${version}</version>
</dependency>启用框架
java
@SpringBootApplication
@EnableLcgylFramework
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}配置
基本配置
yaml
# application.yml
lcgyl:
enabled: true
# 插件配置
plugin:
enabled: true
directory: plugins
scan-packages:
- com.example.plugins
auto-start: true
# 事件总线配置
event:
enabled: true
async: true
thread-pool-size: 10
queue-capacity: 1000
# IoC 容器配置
ioc:
enabled: true
scan-packages:
- com.example.components
lazy-init: false
# AOP 配置
aop:
enabled: true
proxy-target-class: true环境配置
yaml
# application-dev.yml
lcgyl:
event:
async: false # 开发环境同步执行便于调试
# application-prod.yml
lcgyl:
event:
async: true
thread-pool-size: 20配置属性类
java
@ConfigurationProperties(prefix = "lcgyl")
public class LcgylProperties {
private boolean enabled = true;
private PluginProperties plugin = new PluginProperties();
private EventProperties event = new EventProperties();
private IocProperties ioc = new IocProperties();
private AopProperties aop = new AopProperties();
// Getters and Setters
public static class PluginProperties {
private boolean enabled = true;
private String directory = "plugins";
private List<String> scanPackages = new ArrayList<>();
private boolean autoStart = true;
// Getters and Setters
}
public static class EventProperties {
private boolean enabled = true;
private boolean async = true;
private int threadPoolSize = 10;
private int queueCapacity = 1000;
// Getters and Setters
}
}自动配置
核心自动配置
java
@Configuration
@ConditionalOnProperty(name = "lcgyl.enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(LcgylProperties.class)
public class LcgylAutoConfiguration {
@Autowired
private LcgylProperties properties;
@Bean
@ConditionalOnMissingBean
public Container container() {
Container container = new DefaultContainer();
container.setLazyInit(properties.getIoc().isLazyInit());
return container;
}
@Bean
@ConditionalOnMissingBean
public EventBus eventBus() {
EventProperties eventProps = properties.getEvent();
return new DefaultEventBus(
eventProps.isAsync(),
eventProps.getThreadPoolSize(),
eventProps.getQueueCapacity()
);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "lcgyl.plugin.enabled", havingValue = "true")
public PluginManager pluginManager() {
PluginProperties pluginProps = properties.getPlugin();
PluginManager manager = new DefaultPluginManager();
manager.setPluginDirectory(pluginProps.getDirectory());
return manager;
}
}条件配置
java
@Configuration
public class ConditionalConfiguration {
// 当 Redis 可用时启用缓存
@Bean
@ConditionalOnClass(name = "org.springframework.data.redis.core.RedisTemplate")
@ConditionalOnProperty(name = "lcgyl.cache.type", havingValue = "redis")
public CacheService redisCacheService(RedisTemplate<String, Object> redisTemplate) {
return new RedisCacheService(redisTemplate);
}
// 默认内存缓存
@Bean
@ConditionalOnMissingBean(CacheService.class)
public CacheService memoryCacheService() {
return new MemoryCacheService();
}
}组件扫描
自动扫描
java
@SpringBootApplication
@EnableLcgylFramework
@LcgylComponentScan(basePackages = "com.example")
public class Application {
}手动注册
java
@Configuration
public class ComponentConfiguration {
@Bean
public UserService userService(UserRepository userRepository) {
return new UserServiceImpl(userRepository);
}
@Bean
public OrderService orderService(
OrderRepository orderRepository,
UserService userService,
EventBus eventBus) {
return new OrderServiceImpl(orderRepository, userService, eventBus);
}
}事件集成
发布事件
java
@Service
public class OrderService {
@Autowired
private EventBus eventBus;
@Autowired
private ApplicationEventPublisher springEventPublisher;
public Order createOrder(Order order) {
orderRepository.save(order);
// 发布 LCGYL 事件
eventBus.publish(new OrderCreatedEvent(order));
// 发布 Spring 事件
springEventPublisher.publishEvent(new OrderCreatedSpringEvent(this, order));
return order;
}
}监听事件
java
@Component
public class OrderEventListener {
// 监听 LCGYL 事件
@Subscribe
public void onOrderCreated(OrderCreatedEvent event) {
logger.info("LCGYL 事件: 订单创建 {}", event.getOrder().getId());
}
// 监听 Spring 事件
@EventListener
public void onOrderCreatedSpring(OrderCreatedSpringEvent event) {
logger.info("Spring 事件: 订单创建 {}", event.getOrder().getId());
}
// 异步监听
@Subscribe(async = true)
public void onOrderCreatedAsync(OrderCreatedEvent event) {
// 异步处理
}
// 条件监听
@EventListener(condition = "#event.order.totalAmount > 1000")
public void onLargeOrder(OrderCreatedSpringEvent event) {
// 只处理大额订单
}
}事件桥接
java
@Component
public class EventBridge {
@Autowired
private EventBus lcgylEventBus;
@Autowired
private ApplicationEventPublisher springPublisher;
// 将 Spring 事件转发到 LCGYL
@EventListener
public void bridgeSpringToLcgyl(ApplicationEvent event) {
if (event instanceof OrderCreatedSpringEvent springEvent) {
lcgylEventBus.publish(new OrderCreatedEvent(springEvent.getOrder()));
}
}
// 将 LCGYL 事件转发到 Spring
@Subscribe
public void bridgeLcgylToSpring(OrderCreatedEvent event) {
springPublisher.publishEvent(new OrderCreatedSpringEvent(this, event.getOrder()));
}
}AOP 集成
使用 LCGYL AOP
java
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
logger.info("调用方法: {}", joinPoint.getSignature().getName());
}
@Around("@annotation(com.lcgyl.framework.aop.Timed)")
public Object timed(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
try {
return joinPoint.proceed();
} finally {
long duration = System.currentTimeMillis() - start;
logger.info("方法 {} 耗时 {}ms",
joinPoint.getSignature().getName(), duration);
}
}
}使用 Spring AOP
java
@Aspect
@Component
public class TransactionAspect {
@Around("@annotation(org.springframework.transaction.annotation.Transactional)")
public Object handleTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
// 事务处理
return joinPoint.proceed();
}
}插件集成
加载插件
java
@Configuration
@ConditionalOnProperty(name = "lcgyl.plugin.enabled", havingValue = "true")
public class PluginConfiguration {
@Autowired
private PluginManager pluginManager;
@PostConstruct
public void loadPlugins() {
// 扫描并加载插件
pluginManager.loadPlugins();
// 启动所有插件
pluginManager.startPlugins();
}
@PreDestroy
public void unloadPlugins() {
pluginManager.stopPlugins();
pluginManager.unloadPlugins();
}
}插件作为 Spring Bean
java
@Component
public class PluginBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
@Autowired
private PluginManager pluginManager;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 将插件注册为 Spring Bean
for (Plugin plugin : pluginManager.getPlugins()) {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(plugin.getClass())
.getBeanDefinition();
registry.registerBeanDefinition(plugin.getId(), beanDefinition);
}
}
}健康检查
自定义健康指示器
java
@Component
public class LcgylHealthIndicator implements HealthIndicator {
@Autowired
private PluginManager pluginManager;
@Autowired
private EventBus eventBus;
@Override
public Health health() {
Map<String, Object> details = new HashMap<>();
// 检查插件状态
int activePlugins = pluginManager.getActivePlugins().size();
details.put("activePlugins", activePlugins);
// 检查事件总线
details.put("eventBusStatus", eventBus.isRunning() ? "running" : "stopped");
if (activePlugins > 0 && eventBus.isRunning()) {
return Health.up().withDetails(details).build();
} else {
return Health.down().withDetails(details).build();
}
}
}Actuator 端点
java
@Endpoint(id = "lcgyl")
@Component
public class LcgylEndpoint {
@Autowired
private PluginManager pluginManager;
@ReadOperation
public Map<String, Object> info() {
Map<String, Object> info = new HashMap<>();
info.put("version", "1.0.0");
info.put("plugins", pluginManager.getPlugins().stream()
.map(p -> Map.of("id", p.getId(), "status", p.getStatus()))
.collect(Collectors.toList()));
return info;
}
@WriteOperation
public void reloadPlugins() {
pluginManager.reloadPlugins();
}
}测试支持
测试配置
java
@SpringBootTest
@TestPropertySource(properties = {
"lcgyl.plugin.enabled=false",
"lcgyl.event.async=false"
})
public class ApplicationTest {
@Autowired
private UserService userService;
@Test
public void testUserService() {
User user = userService.findById(1L);
assertNotNull(user);
}
}Mock 支持
java
@SpringBootTest
public class OrderServiceTest {
@MockBean
private EventBus eventBus;
@Autowired
private OrderService orderService;
@Test
public void testCreateOrder() {
Order order = new Order();
orderService.createOrder(order);
verify(eventBus).publish(any(OrderCreatedEvent.class));
}
}最佳实践
1. 配置分离
yaml
# application.yml - 通用配置
lcgyl:
enabled: true
# application-dev.yml - 开发配置
lcgyl:
event:
async: false
# application-prod.yml - 生产配置
lcgyl:
event:
async: true
thread-pool-size: 202. 条件加载
java
@Configuration
@ConditionalOnProperty(name = "lcgyl.feature.enabled", havingValue = "true")
public class FeatureConfiguration {
// 只在功能启用时加载
}3. 优雅关闭
java
@Component
public class GracefulShutdown implements DisposableBean {
@Autowired
private PluginManager pluginManager;
@Autowired
private EventBus eventBus;
@Override
public void destroy() {
logger.info("开始优雅关闭...");
pluginManager.stopPlugins();
eventBus.shutdown();
logger.info("优雅关闭完成");
}
}常见问题
Q: LCGYL 组件和 Spring Bean 如何互相注入?
A: LCGYL 组件自动注册为 Spring Bean,可以使用 @Autowired 或 @Inject 互相注入。
Q: 如何禁用某个自动配置?
A: 使用配置属性或排除注解:
java
@SpringBootApplication(exclude = {PluginAutoConfiguration.class})或
yaml
lcgyl:
plugin:
enabled: falseQ: 事件是否支持事务?
A: 可以使用 @TransactionalEventListener 在事务提交后发布事件。
下一步
- Spring Data 集成 - 数据访问
- Spring Security 集成 - 安全认证
- Spring Cloud 集成 - 微服务