1

I want to use @Qualifier to dynamically specifying parameters? how to do it ?

@Qualifier("two") 'two' as a parameter ,can be 'one' 'three' or other.

Can i use aop dynamically design 'two'?

means I want to change the name of service with a @Qualifier by parameters.

the parameter from the url 'Token'.

case: url: http://localhost:8080/insert/order, token has a parameter: 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");
    }

}
7
  • You may want to have a look at @Conditional, though currently it is not entirely clear what you want to achieve... do you want to change the name of your services with a @Qualifier or do you want to insert a different service depending on a dynamic @Qualifier -> please specify, best with an edit Commented Jan 15, 2019 at 6:46
  • Yes . I want to change the name of service with a @Qualifier by parameters. Commented Jan 15, 2019 at 7:58
  • 1
    and why would you like to do that in the first place? What problem are you faceing? Commented Jan 15, 2019 at 8:02
  • 1
    Can't you just define one single service which acts differently on the kind of input one, two, three, four? Commented Jan 15, 2019 at 8:11
  • I added the question. I hope you can unstand. nwo , my project has a APi .For example:localhost:8080/insert/order , As more and more customers, different customers' order processing is different. But the interface and parameters are the same, so I hope to have different implementations.CustomerID, which can be obtained in the url token. Commented Jan 15, 2019 at 8:14

3 Answers 3

3

你好 !

No you cannot , mostly because the attribute in Java annotation does not allow to assign with variables.

Actually you want to choose an implementation to use based on some runtime conditions(i.e.companyId in your case). You can achieve it using factory pattern with @Configuration and @Bean which is much more elegant and easier to understand than your ugly AOP solution:

First define a factory:

@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
        }
   }
}

In the controller , inject the ServiceFactory to get the related Service based on the the company Id

@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();
       }

}
Sign up to request clarification or add additional context in comments.

1 Comment

AOP is mainly used for addressing the cross cutting concern such as authorisation , security stuff etc . So you can keep on using AOP for such things. But for the business logic , I would recommend using my suggested factory pattern , which is much more good looking than your AOP solution which to be honest , too ugly for me :P) . But the most important points is that you AOP solution will fail if there are different company to access your API at the same time as it is possible companyA base service is replaced by companyB base service ....
0

Inject (autowire) ApplicationContext into your class and use one of getBeans* method to find the exact bean you need.

1 Comment

yes, but each url must be implemented differently service, how to do it with AOP?
0

aspect

@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);
    }

}

control

@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

@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");
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.