为了账号安全,请及时绑定邮箱和手机立即绑定

如何创建用于拆分请求参数并收集返回结果的自定义注释?

如何创建用于拆分请求参数并收集返回结果的自定义注释?

婷婷同学_ 2021-11-17 17:22:16
我有一个方法 params 是一个大于 50000 个项目的列表;限于业务逻辑,列表必须小于30000,这样我才有办法在逻辑之前把这个数组拆分成二维数组public static final <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int size) {        AtomicInteger counter = new AtomicInteger(0);        return inputList.stream().collect(Collectors.groupingBy(s -> counter.getAndIncrement() / size)).values();}这是我目前的解决方案:public List<Account> getChildrenList(List<Long> ids) {        List<Account> childrenList = new ArrayList<>();        Collection<List<Long>> childrenId2dList = PartitionArray.partitionBasedOnSize(childrenIdsList, 30000);        for (List<Long> list : childrenId2dList) {            //this is my business logic: start            childrenList.addAll(accountRepository.getAccounts(list));            //this is my business logic: end        }        return childrenAccountsList;}我想在方法之上创建一个注释而不是许多重复的代码(每次都检查和恶意...)对不起,我的英语不好,我画了一个图表:方法调用>恶意数组>业务逻辑>收集所有结果>返回
查看完整描述

2 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

在我看来,在这种情况下使用注释有点过度设计(您必须编写注释处理器)。您可以轻松地使用泛型和lambda 表达式和/或方法引用来实现您的目标。例如:


以PartitionArray这种方式更新:


import java.util.ArrayList;

import java.util.Collection;

import java.util.List;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.function.Function;

import java.util.stream.Collectors;


public class PartitionArray {


    private static <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int partitionSize) {

        Collection<List<T>> collection = new ArrayList<>();

        int remainingSize = inputList.size();

        int index = 0;

        while (remainingSize > partitionSize) {

            collection.add(inputList.subList(index, index + partitionSize));

            remainingSize -= partitionSize;

            index += partitionSize;

        }

        collection.add(inputList.subList(index, index + remainingSize));

        return collection;

    }


    public static <D, T> List<D> partitionAndDoBusinessFunction(List<T> ids, Function<List<T>, List<D>> businessFunction, int partitionSize) {

        List<D> dataList = new ArrayList<>();

        Collection<List<T>> idListCollection = partitionBasedOnSize(ids, partitionSize);

        for (List<T> idList : idListCollection) {

            dataList.addAll(businessFunction.apply(idList));

        }

        return dataList;

    }

}

然后只需从您的AccountService(使用方法参考)中使用它:


import java.util.List;


public class AccountService {


    private AccountRepository accountRepository;


    public List<Account> getAccounts(List<Long> ids) {

        return PartitionArray.partitionAndDoBusinessFunction(ids, accountRepository::getAccounts, 30000);

    }

}

或者使用 lambda 表达式:


import java.util.List;


public class AccountService {


    private AccountRepository accountRepository;


    public List<Account> getAccounts(List<Long> ids) {

        return PartitionArray.partitionAndDoBusinessFunction(ids, idList -> {

            List<Account> accounts = accountRepository.getAccounts(idList);

            // do more business on accounts

            return accounts;

        }, 30000);

    }

}


查看完整回答
反对 回复 2021-11-17
?
守着一只汪

TA贡献1872条经验 获得超3个赞

这是使用annotations的解决方案,使用AspectJ:


首先,定义所需的注释:


package partition;


import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Partitioned {


    /**

     * The size of the partition, for instance 30000

     */

    int size();

}

因此,您的服务将如下所示:


package partition;


import java.util.List;


public class AccountService {


    private AccountRepository accountRepository;


    public AccountService(AccountRepository accountRepository) {

        this.accountRepository = accountRepository;

    }


    @Partitioned(size = 30000)

    public List<Account> getAccounts(List<Long> ids) {

        return accountRepository.getAccounts(ids);

    }

}

到目前为止,这很容易。然后是注解的处理,AspectJ 进入游戏。定义链接到注释的方面:


package partition;


import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;


import java.util.ArrayList;

import java.util.Collection;

import java.util.List;


@Aspect

public class PartitionedAspect {


    @Pointcut("@annotation(partitioned)")

    public void callAt(Partitioned partitioned) {

    }


    @Around("callAt(partitioned)")

    public <T, D> Object around(ProceedingJoinPoint pjp, Partitioned partitioned) throws Throwable {

        List<T> inputIds = (List) pjp.getArgs()[0];

        if (inputIds.size() > partitioned.size()) {

            List<D> dataList = new ArrayList<>();

            Collection<List<T>> partitionedIds = PartitionArray.partitionBasedOnSize(inputIds, partitioned.size());

            for (List<T> idList : partitionedIds) {

                List<D> data = (List) pjp.proceed(new Object[]{idList});

                dataList.addAll(data);

            }

            return dataList;

        }

        return pjp.proceed();

    }

}

当然,您必须导入AspectJ,并在编译时做一些额外的事情。假设您使用的是 maven,请将这些行添加到您的pom.xml(插件和依赖项)中:


<build>

    <plugins>

        ...

        <plugin>

            <groupId>org.codehaus.mojo</groupId>

            <artifactId>aspectj-maven-plugin</artifactId>

            <version>1.7</version>

            <configuration>

                <complianceLevel>1.8</complianceLevel>

                <source>1.8</source>

                <target>1.8</target>

                <showWeaveInfo>true</showWeaveInfo>

                <verbose>true</verbose>

                <Xlint>ignore</Xlint>

                <encoding>UTF-8</encoding>

            </configuration>

            <executions>

                <execution>

                    <goals>

                        <goal>compile</goal>

                        <goal>test-compile</goal>

                    </goals>

                </execution>

            </executions>

        </plugin>

    </plugins>

</build>


<dependencies>

    ...

    <dependency>

        <groupId>org.aspectj</groupId>

        <artifactId>aspectjrt</artifactId>

        <version>${aspectj.version}</version>

    </dependency>

    <dependency>

        <groupId>org.aspectj</groupId>

        <artifactId>aspectjweaver</artifactId>

        <version>${aspectj.version}</version>

    </dependency>

...

</dependencies>


查看完整回答
反对 回复 2021-11-17
  • 2 回答
  • 0 关注
  • 138 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信