Skip to content

独立使用

不依赖 Spring,使用 LCGYL Framework 原生能力构建应用。

快速开始

1. 添加依赖

pom.xml 中添加:

xml
<dependencies>
    <!-- LCGYL 核心框架 -->
    <dependency>
        <groupId>com.lcgyl</groupId>
        <artifactId>lcgyl-framework-core</artifactId>
        <version>${lcgyl.version}</version>
    </dependency>
    
    <!-- 需要的插件 -->
    <dependency>
        <groupId>com.lcgyl</groupId>
        <artifactId>lcgyl-web-plugin</artifactId>
        <version>${lcgyl.version}</version>
    </dependency>
    <dependency>
        <groupId>com.lcgyl</groupId>
        <artifactId>lcgyl-cache-plugin</artifactId>
        <version>${lcgyl.version}</version>
    </dependency>
</dependencies>

或在 build.gradle 中添加:

gradle
dependencies {
    implementation 'com.lcgyl:lcgyl-framework-core'
    implementation 'com.lcgyl:lcgyl-web-plugin'
    implementation 'com.lcgyl:lcgyl-cache-plugin'
}

2. 创建应用

java
@ComponentScan("com.example.app")
public class Application {
    
    public static void main(String[] args) {
        // 创建应用
        LcgylApplication app = LcgylApplication.create(Application.class);
        
        // 加载插件
        app.loadPlugin("lcgyl-web-plugin");
        app.loadPlugin("lcgyl-cache-plugin");
        
        // 启动应用
        app.start();
        
        // 启动 Web 服务器
        app.startWebServer(8080);
    }
}

3. 配置应用

创建 application.properties

properties
# 应用配置
app.name=My Application
app.version=1.0.0

# Web 配置
web.server.port=8080
web.server.contextPath=/api

# 数据源配置
datasource.url=jdbc:mysql://localhost:3306/db
datasource.username=root
datasource.password=password
datasource.maxPoolSize=20

使用插件

Web 插件

创建控制器

java
@RestController("/users")
public class UserController {
    
    @Inject
    private UserService userService;
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
    
    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
}

配置 Web 服务器

java
@Component
public class WebConfig {
    
    @Inject
    private Configuration config;
    
    public WebServer webServer() {
        return WebServer.builder()
            .port(config.getInt("web.server.port", 8080))
            .contextPath(config.getString("web.server.contextPath", "/"))
            .staticLocations("/static", "/public")
            .cors(cors -> cors
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
            )
            .build();
    }
}

数据访问插件

创建 Repository

java
@Component
public class UserRepository {
    
    @Inject
    private JdbcTemplate jdbcTemplate;
    
    public Optional<User> findById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.queryForOptional(sql, User.class, id);
    }
    
    @Transactional
    public User save(User user) {
        if (user.getId() == null) {
            String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
            Long id = jdbcTemplate.insert(sql, user.getName(), user.getEmail());
            user.setId(id);
        } else {
            String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
            jdbcTemplate.update(sql, user.getName(), user.getEmail(), user.getId());
        }
        return user;
    }
}

配置数据源

java
@Component
public class DataSourceConfig {
    
    @Inject
    private Configuration config;
    
    public DataSource dataSource() {
        return DataSourceBuilder.create()
            .url(config.getString("datasource.url"))
            .username(config.getString("datasource.username"))
            .password(config.getString("datasource.password"))
            .maxPoolSize(config.getInt("datasource.maxPoolSize", 20))
            .build();
    }
}

消息队列插件

发送消息

java
@Component
public class OrderService {
    
    @Inject
    private MessageProducer messageProducer;
    
    @Inject
    private OrderRepository orderRepository;
    
    @Transactional
    public void createOrder(Order order) {
        // 保存订单
        orderRepository.save(order);
        
        // 发送消息
        messageProducer.send("order.created", order);
    }
}

接收消息

java
@Component
public class OrderListener {
    
    @MessageListener(topic = "order.created")
    public void onOrderCreated(Order order) {
        System.out.println("订单已创建: " + order.getId());
        
        // 处理订单
        processOrder(order);
    }
    
    private void processOrder(Order order) {
        // 业务逻辑
    }
}

配置消息队列

properties
# RabbitMQ 配置
messaging.type=rabbitmq
messaging.rabbitmq.host=localhost
messaging.rabbitmq.port=5672
messaging.rabbitmq.username=guest
messaging.rabbitmq.password=guest
java
@Component
public class MessagingConfig {
    
    @Inject
    private Configuration config;
    
    public MessageProducer messageProducer() {
        return MessageProducer.builder()
            .host(config.getString("messaging.rabbitmq.host"))
            .port(config.getInt("messaging.rabbitmq.port"))
            .username(config.getString("messaging.rabbitmq.username"))
            .password(config.getString("messaging.rabbitmq.password"))
            .build();
    }
}

安全插件

配置认证

java
@Component
public class SecurityConfig {
    
    public SecurityFilterChain securityFilterChain() {
        return SecurityFilterChain.builder()
            .authorizeRequests(auth -> auth
                .antMatchers("/public/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/")
            )
            .build();
    }
}

使用认证

java
@RestController("/auth")
public class AuthController {
    
    @Inject
    private AuthenticationService authService;
    
    @PostMapping("/login")
    public LoginResponse login(@RequestBody LoginRequest request) {
        String token = authService.authenticate(
            request.getUsername(),
            request.getPassword()
        );
        return new LoginResponse(token);
    }
    
    @GetMapping("/user")
    @RequiresAuthentication
    public User getCurrentUser(@CurrentUser User user) {
        return user;
    }
}

IoC 容器

组件注册

java
// 自动扫描
@ComponentScan("com.example.app")
public class Application {
}

// 手动注册
Container container = Container.getInstance();
container.register(UserService.class);
container.register("userService", new UserService());

依赖注入

java
// 构造器注入(推荐)
@Component
public class UserService {
    
    private final UserRepository userRepository;
    
    @Inject
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

// 字段注入
@Component
public class UserService {
    
    @Inject
    private UserRepository userRepository;
}

作用域

java
// 单例(默认)
@Component
public class UserService {
}

// 原型
@Component(scope = Scope.PROTOTYPE)
public class UserService {
}

事件总线

发布事件

java
@Component
public class UserService {
    
    @Inject
    private EventBus eventBus;
    
    public void createUser(User user) {
        userRepository.save(user);
        
        // 发布事件
        eventBus.publish(new UserCreatedEvent(user));
    }
}

订阅事件

java
@Component
public class EmailService {
    
    @EventListener
    public void onUserCreated(UserCreatedEvent event) {
        User user = event.user();
        sendWelcomeEmail(user.getEmail());
    }
}

配置管理

加载配置

java
// 加载配置文件
Configuration config = ConfigurationManager.load("application.properties");

// 获取配置
String appName = config.getString("app.name");
int port = config.getInt("web.server.port", 8080);

配置绑定

java
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String name;
    private String version;
    
    // Getters and Setters
}

// 使用
AppConfig appConfig = ConfigurationManager.bind(AppConfig.class, config);

完整示例

应用主类

java
@ComponentScan("com.example.blog")
public class BlogApplication {
    
    public static void main(String[] args) {
        // 创建应用
        LcgylApplication app = LcgylApplication.create(BlogApplication.class);
        
        // 加载配置
        Configuration config = ConfigurationManager.load("application.properties");
        
        // 加载插件
        app.loadPlugin("lcgyl-web-plugin");
        app.loadPlugin("lcgyl-cache-plugin");
        app.loadPlugin("lcgyl-security-plugin");
        
        // 启动应用
        app.start();
        
        // 启动 Web 服务器
        int port = config.getInt("web.server.port", 8080);
        app.startWebServer(port);
        
        System.out.println("应用已启动: http://localhost:" + port);
    }
}

控制器

java
@RestController("/api/articles")
public class ArticleController {
    
    @Inject
    private ArticleService articleService;
    
    @GetMapping
    public List<Article> listArticles() {
        return articleService.findAll();
    }
    
    @GetMapping("/{id}")
    public Article getArticle(@PathVariable Long id) {
        return articleService.findById(id);
    }
    
    @PostMapping
    @RequiresAuthentication
    public Article createArticle(
        @RequestBody Article article,
        @CurrentUser User user
    ) {
        article.setUserId(user.getId());
        return articleService.save(article);
    }
}

服务层

java
@Component
public class ArticleService {
    
    @Inject
    private ArticleRepository articleRepository;
    
    @Inject
    private EventBus eventBus;
    
    public List<Article> findAll() {
        return articleRepository.findAll();
    }
    
    public Article findById(Long id) {
        return articleRepository.findById(id)
            .orElseThrow(() -> new NotFoundException("文章不存在"));
    }
    
    @Transactional
    public Article save(Article article) {
        article = articleRepository.save(article);
        eventBus.publish(new ArticleCreatedEvent(article));
        return article;
    }
}

性能对比

指标独立使用Spring Boot
启动时间~500ms~3000ms
内存占用~100MB~300MB
JAR 大小~10MB~50MB
依赖数量~5~50+

最佳实践

1. 使用构造器注入

java
// ✅ 推荐
@Component
public class UserService {
    
    private final UserRepository userRepository;
    
    @Inject
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

2. 配置外部化

properties
# application.properties
datasource.url=${DB_URL:jdbc:mysql://localhost:3306/db}
datasource.username=${DB_USERNAME:root}
datasource.password=${DB_PASSWORD:password}

3. 使用事件解耦

java
// 发布事件
eventBus.publish(new OrderCreatedEvent(order));

// 订阅事件
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
    // 处理
}

4. 资源清理

java
public class Application {
    
    public static void main(String[] args) {
        LcgylApplication app = LcgylApplication.create(Application.class);
        
        // 注册关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            app.stop();
        }));
        
        app.start();
    }
}

常见问题

Q: 如何热加载插件?

java
PluginManager pluginManager = app.getPluginManager();
pluginManager.reloadPlugin("lcgyl-web-plugin");

Q: 如何自定义组件扫描?

java
@ComponentScan(
    basePackages = {"com.example.app", "com.example.lib"},
    excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test")
)
public class Application {
}

Q: 如何处理配置文件不存在?

java
try {
    Configuration config = ConfigurationManager.load("application.properties");
} catch (ConfigurationException e) {
    // 使用默认配置
    Configuration config = Configuration.empty();
}

下一步

Released under the Apache License 2.0