Я хочу использовать @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");
}
}
Да . Я хочу изменить имя службы с помощью @Qualifier по параметрам.
и зачем вам вообще это нужно? С какой проблемой вы столкнулись?
Разве вы не можете просто определить одну единственную службу, которая по-разному действует на тип входного one, two, three, four?
Я добавил вопрос. Надеюсь, ты сможешь понять. nwo, у моего проекта есть APi. Например: локальный: 8080 / вставить / заказ, Чем больше и больше клиентов, обработка заказов у разных клиентов разная. Но интерфейс и параметры такие же, поэтому я надеюсь, что будут разные реализации. CustomerID, который можно получить в токене url.
Возможно, я не могу очень четко описать свою проблему, я не знаю, понимаете ли вы, что это какая-то ошибка. В любом случае, большое спасибо, это мое решение: stackoverflow.com/a/54195074/9185993. Не знаю, есть ли план получше.




Внедрите (autowire) ApplicationContext в свой класс и используйте один из методов getBeans *, чтобы найти именно тот компонент, который вам нужен.
да, но каждый url должен быть реализован по разному сервису, как это сделать с АОП?
аспект
@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来实现。不知道这样做和你给的解决方法)(工厂模式)对比的话,哪个更好?
АОП в основном используется для решения сквозных проблем, таких как авторизация, безопасность и т. д. Так что вы можете продолжать использовать АОП для таких вещей. Но для бизнес-логики я бы рекомендовал использовать предложенный мной шаблон фабрики, который намного красивее, чем ваше решение АОП, которое, честно говоря, слишком уродливо для меня: P). Но наиболее важным моментом является то, что ваше AOP-решение выйдет из строя, если к вашему API одновременно будут обращаться разные компании, поскольку это возможно, базовая услуга companyA заменяется базовой услугой companyB ....
THX, я понимаю.
Возможно, вы захотите взглянуть на
@Conditional, хотя в настоящее время не совсем понятно, чего вы хотите достичь ... хотите ли вы изменить имя своих служб с помощью@Qualifierили хотите вставить другую службу в зависимости от динамический@Qualifier-> укажите, лучше всего с редактировать