Как использовать динамически определяющие параметры @Qualifier?

Я хочу использовать @Qualifier для динамического определения параметров? как это сделать ?

@Qualifier ("два") 'два' в качестве параметра , может быть 'один' 'три' или другое.

Могу ли я использовать aop с динамическим дизайном «два»?

означает, что я хочу изменить имя службы на @Qualifier по параметрам.

параметр из URL-адреса 'Token'.

case: url: http: // локальный: 8080 / вставить / заказ, токен имеет параметр: companyId = one


@RestController
public class ApiWebService {
       @Autowired
       @Qualifier("two")
      //@Qualifier("one")
       private BaseService baseService;

       @GetMapping("insert/order")
       public void test() {
            baseService.insertOrder();
       }

}


@Service("one")
public class CompanyOneService extends BaseService {

    @Override
    public void insertOrder() {
        System.out.println("conpanyOne");
        System.out.println("baseInsertOrder");
    }
}

@Service("two")
public class CompanyTwoService extends BaseService {

    @Override
    public void insertOrder(){
        System.out.println("companyTwo");
        System.out.println("baseInsertOrder");
    }
}

three
four
...

@Service
public class BaseService {

    public void insertOrder(){
        System.out.println("baseInsertOrder");
    }

}

Возможно, вы захотите взглянуть на @Conditional, хотя в настоящее время не совсем понятно, чего вы хотите достичь ... хотите ли вы изменить имя своих служб с помощью @Qualifier или хотите вставить другую службу в зависимости от динамический @Qualifier -> укажите, лучше всего с редактировать

Lino 15.01.2019 07:46

Да . Я хочу изменить имя службы с помощью @Qualifier по параметрам.

beer 15.01.2019 08:58

и зачем вам вообще это нужно? С какой проблемой вы столкнулись?

Lino 15.01.2019 09:02

Разве вы не можете просто определить одну единственную службу, которая по-разному действует на тип входного one, two, three, four?

Lino 15.01.2019 09:11

Я добавил вопрос. Надеюсь, ты сможешь понять. nwo, у моего проекта есть APi. Например: локальный: 8080 / вставить / заказ, Чем больше и больше клиентов, обработка заказов у ​​разных клиентов разная. Но интерфейс и параметры такие же, поэтому я надеюсь, что будут разные реализации. CustomerID, который можно получить в токене url.

beer 15.01.2019 09:14

Возможно, я не могу очень четко описать свою проблему, я не знаю, понимаете ли вы, что это какая-то ошибка. В любом случае, большое спасибо, это мое решение: stackoverflow.com/a/54195074/9185993. Не знаю, есть ли план получше.

beer 15.01.2019 09:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
1 391
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Внедрите (autowire) ApplicationContext в свой класс и используйте один из методов getBeans *, чтобы найти именно тот компонент, который вам нужен.

да, но каждый url должен быть реализован по разному сервису, как это сделать с АОП?

beer 15.01.2019 09:20

аспект

@Aspect
@Component
public class ApiAspect {

    @Pointcut("execution(* com.example.demo.control.ApiWebService.*(..))")
    public void apiInputWebService() {

    }

    @Before("apiInputWebService()")
    public void apiInputAuth(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes())
                .getRequest();
        String token = request.getHeader("Authorization");

        //compangId can be from token
        String compangId = "one";
        Object target = joinPoint.getTarget();
        Method method = target.getClass().getMethod("before", String.class);
        method.invoke(target, compangId);
    }

}

контроль

@RestController
public class ApiWebService {

    private ApiService baseService;

    @Autowired
    private ApplicationContext applicationContext;

    public void before(String company) {
        baseService = (ApiService) applicationContext.getBean(company);
    }

    @GetMapping("insert/order")
    public void test() {
        baseService.insertOrder();
    }
}

услуга

@Service
public class ApiService {

    public void insertOrder(){
        System.out.println("baseInsertOrder");
    }

}

@Service("one")
public class CompanyOneService extends ApiService {

    @Override
    public void insertOrder() {
        System.out.println("conpanyOne");
        System.out.println("baseInsertOrder");
    }
}

@Service("two")
public class CompanyTwoService extends ApiService {

    @Override
    public void insertOrder(){
        System.out.println("companyTwo");
        System.out.println("baseInsertOrder");
    }
}
Ответ принят как подходящий

你好!

Нет, вы не можете, в основном потому, что атрибут в аннотации Java не позволяет назначать переменные.

На самом деле вы хотите выбрать реализацию для использования на основе некоторых условий выполнения (например, companyId в вашем случае). Вы можете добиться этого, используя фабричный шаблон с @Configuration и @Bean, который намного элегантнее и проще для понимания, чем ваше уродливое решение AOP:

Сначала определите фабрику:

@Configuration
public class ServiceFactory{

   @Bean
   public  BaseService companyOneService(){
     return new CompanyOneService();
   }

   @Bean
   public  BaseService companyTwoService(){
     return new CompanyTwoService();
   }

   public BaseService getService(Integer companyId){
        if (companyId == 1){
            return companyOneService();
        }else if (company==2){
            return companyTwoService();
        }else{
            //blablablab
        }
   }
}

В контроллере введите ServiceFactory, чтобы получить соответствующую услугу на основе идентификатора компании.

@RestController
public class ApiWebService {

       @Autowired
       private ServiceFactory serviceFactory;

       @GetMapping("insert/order")
       public void test() {
            Integer companyId = getCompanyIdFromToken(httpServletRequest); 
            BaseService service = serviceFactory.getService(companyId);
            service.blablabla();
       }

}

哈哈 ! 你好呀!看到你给的解决方法之前 我用 aop 实现了 stackoverflow.com/a/54195074/9185993 ,在执行目标方法前,先执行before方法,获取实例 。 希望你可以看一下 给点意见 。说一下这边用aop 的原因是 : control 层上有 权限的的校验 , 校验 token 用的 ,本身有个aop ,所以就想用aop来实现。不知道这样做和你给的解决方法)(工厂模式)对比的话,哪个更好?

beer 15.01.2019 09:55

АОП в основном используется для решения сквозных проблем, таких как авторизация, безопасность и т. д. Так что вы можете продолжать использовать АОП для таких вещей. Но для бизнес-логики я бы рекомендовал использовать предложенный мной шаблон фабрики, который намного красивее, чем ваше решение АОП, которое, честно говоря, слишком уродливо для меня: P). Но наиболее важным моментом является то, что ваше AOP-решение выйдет из строя, если к вашему API одновременно будут обращаться разные компании, поскольку это возможно, базовая услуга companyA заменяется базовой услугой companyB ....

Ken Chan 15.01.2019 10:05

THX, я понимаю.

beer 15.01.2019 10:13

Другие вопросы по теме