• ff4j aop模式动态bean 切换


    ff4j 提供了基于aop模式的开发,我们只需要使用简单的注解,以及一个远端存储(中心化控制)就可以方便的动态调整
    线上bean的选择,以下是一个简单的demo(使用mysql中心化存储)

    环境准备

    • docker-compose 文件
     
    version: "3"
    services:
      mysql:
        image: mysql:5.7.16
        ports:
          - 3306:3306
        command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
        environment:
          MYSQL_ROOT_PASSWORD: dalongrong
          MYSQL_DATABASE: ff4j_v1
          TZ: Asia/Shanghai

    项目准备

    • 项目结构
    ├── docker-compose.yaml
    ├── pom.xml
    └── src
        └── main
            ├── java
            └── org
            └── ff4j
            └── sample
            ├── Application.java
            ├── config
            └── FF4JConfiguration.java
            ├── resources
            └── SampleResource.java
            └── service
            ├── GreetingService.java
            └── impl
            ├── GreetingServiceEnglishImpl.java
            └── GreetingServiceFrenchImpl.java
            └── resources
                └── application.properties
    • pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://maven.apache.org/POM/4.0.0"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.ff4j</groupId>
        <artifactId>ff4j-sample-springboot-jdbc</artifactId>
        <packaging>jar</packaging>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.4.RELEASE</version>
        </parent>
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
            <ff4j.version>1.8.4</ff4j.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.ff4j</groupId>
                <artifactId>ff4j-spring-boot-starter</artifactId>
                <version>${ff4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.ff4j</groupId>
                <artifactId>ff4j-store-springjdbc</artifactId>
                <version>${ff4j.version}</version>
            </dependency>
             <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-dbcp2</artifactId>
            </dependency>
             <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
        </dependencies>
        <build>
            <sourceDirectory>src/main/java</sourceDirectory>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                </resource>
            </resources>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    • 代码说明
      ff4j 提供的aop注解,可以方便的进行bean切换管理
      参考格式:
     
    public interface GreetingService {
        @Flip(name="language-french", alterClazz = GreetingServiceFrenchImpl.class)
        String sayHello(String name);
    }

    说明:
    当language-french 为true 的时候使用GreetingServiceFrenchImpl这个实现
    接口的几个实现
    GreetingServiceEnglishImpl.java
    注意添加了Primary,为了使用上便捷

     
    package org.ff4j.sample.service.impl;
    import org.ff4j.sample.service.GreetingService;
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    @Component()
    @Primary
    public class GreetingServiceEnglishImpl implements GreetingService {
        public String sayHello(String name) {
            return "Hello " + name;
        }
    }

    GreetingServiceFrenchImpl.java

    package org.ff4j.sample.service.impl;
    import org.ff4j.sample.service.GreetingService;
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    @Component()
    public class GreetingServiceFrenchImpl implements GreetingService {
        public String sayHello(String name) {
            return "Bonjour " + name;
        }
    }

    引用bean
    SampleResource.java

     
    package org.ff4j.sample.resources;
    import org.ff4j.FF4j;
    import org.ff4j.sample.service.GreetingService;
    import org.ff4j.spring.autowire.FF4JFeature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class SampleResource {
        @Autowired
        private FF4j getFF4j;
        @Autowired
        private GreetingService greeting;
        @RequestMapping(value = "/", method = RequestMethod.GET, produces = "text/html")
        public String sayHello() {
            StringBuilder response = new StringBuilder("<html><body><ul>");
            response.append("<p>Is <span style="color:red">Awesome</span> feature activated ? from ff4j.check("feature_X") <span style="color:blue">");
            response.append(getFF4j.check("feature_X"));
            response.append("</span></body></html>");
            return response.toString();
        }
        // 引用bean,基于配置的注解
        @RequestMapping(value = "/msg", method = RequestMethod.GET, produces = "text/html")
        public String sayHelloMessage() {
           String message = greeting.sayHello("CLU");
           return message;
        }
    }

    FF4JConfiguration.java
    主要是配置ff4j bean

     
    package org.ff4j.sample.config;
    import javax.sql.DataSource;
    import org.ff4j.FF4j;
    import org.ff4j.springjdbc.store.EventRepositorySpringJdbc;
    import org.ff4j.springjdbc.store.FeatureStoreSpringJdbc;
    import org.ff4j.springjdbc.store.PropertyStoreSpringJdbc;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    @Configuration()
    public class FF4JConfiguration {
        @Autowired
        private DataSource dataSource;
        @Bean
        public FF4j getFF4j() {
            FF4j ff4j = new FF4j();
            ff4j.setFeatureStore(new FeatureStoreSpringJdbc(dataSource));
            ff4j.setPropertiesStore(new PropertyStoreSpringJdbc(dataSource));
            ff4j.setEventRepository(new EventRepositorySpringJdbc(dataSource));
            ff4j.audit(true);
            ff4j.createSchema();
            ff4j.autoCreate(true);
            return ff4j;
        }
    }

    spring boot 应用配置

    spring.datasource.name=ff4j_db
    spring.datasource.url=jdbc:mysql://localhost:3306/ff4j_v1
    spring.datasource.driverClassName=com.mysql.jdbc.Driver 
    spring.datasource.username=root
    debug=true
    spring.datasource.password=dalongrong
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver

    运行&&效果

    • 启动mysql
    docker-compose up -d
    • 启动服务
    mvn spring-boot:run
    • 效果

    从配置上默认应该是GreetingServiceEnglishImpl的,当我们启用language-french 会使用GreetingServiceFrenchImpl的实现


    启用language-french特性(修改数据库数据)


    访问效果

    参考资料

    https://github.com/ff4j/ff4j/wiki/Advanced-Concepts#aspect-oriented-programming

  • 相关阅读:
    utils:一个通用枚举类
    代码片段(二):SQL片段
    Scala:(一) 特点及安装环境配置
    Scala:(二) 语言基础-数据结构、表达式(判断、循环、块表达式)
    11-docker搭建mysql一主一从
    10-docker搭建rabbitmq集群
    尚硅谷周阳面试第二季
    docker 修改mysql 表大小写铭感
    volatile的理解
    消息队列优缺点及其选型
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/12739882.html
Copyright © 2020-2023  润新知