我有一个用于登录功能的抽象类
@Component
public abstract class SignIn {
public abstract LogInOperationToken signin(User user, HttpServletRequest request);
}
由两个具体的类FacebookSignInImpl
和NormalSignInImpl
实现,它们也被注释为@Component
。
现在,我有一个服务类如下:
@Service
public class SignInService {
@Autowired(required = true)
private SignIn signIn;
public SignInService(@Qualifier("signIn") SignIn signin) {
this.signIn = signin;
}
public LogInOperationToken signin(User user, HttpServletRequest request) {
return signIn.signin(user,request);
}
}
如您所见,它将抽象类作为构造函数参数。
从控制器类我想要实现的是检查一些标志并基于此,为抽象类分配正确的实现:normal或facebook signin。如果没有Spring依赖注入,我会做类似的事情:
SignIn signIn = null;
if(flag.equals("facebook")){
signIn = new FacebookSignInImpl();
}
else{
signIn = new NormalSignInImpl();
}
SignInService signInService = new SignInService(signIn);
signInService.signIn(user, request);
由于SignIn
是抽象类,我怎样才能@Autowire
它,以便将它分配给SignInService
中的构造函数。如果您需要进一步澄清,请发表评论。感谢。
答案 0 :(得分:2)
您无法创建抽象类的@Component
,并且您的应用程序设计并不完美。请遵循以下模式
public abstract class SignIn {
public abstract LogInOperationToken signin(User user, HttpServletRequest request);
}
@Component("fcaebookSignIn")
public class FcaebookSignIn {
public LogInOperationToken signin(User user, HttpServletRequest request) {
// implementation code
}
}
@Component("normalSignIn")
public class NormalSignIn {
public LogInOperationToken signin(User user, HttpServletRequest request) {
// implementation code
}
}
然后我强烈建议您为不同类型的signIn
创建不同的控制器或休息端点@Controller
public class SignInController {
@Autowired
@Qualifier(value="fcaebookSignIn")
private SignIn fcaebookSignIn;
@Autowired
@Qualifier(value="normalSignIn")
private SignIn normalSignIn;
@RequestMapping (method = RequestMethod.POST, path = '/normal/signIn')
public User normalSignIn(@RequestBody User user, HttpServletRequest request) {
normalSignIn.signIn(user, request);
}
@RequestMapping (method = RequestMethod.POST, path = '/facebook/signIn')
public User facebookSignIn(@RequestBody User user, HttpServletRequest request) {
fcaebookSignIn.signIn(user, request);
}
}
但是如果你必须使用一个端点,那么以下内容应该可以正常工作
@Controller
public class SignInController {
@Autowired
private ApplicationContext context;
private SignIn signIn;
@RequestMapping (method = RequestMethod.POST, path = '/signIn')
public User normalSignIn(@RequestBody User user, HttpServletRequest request) {
String flag = request.getParameter("flag"); // populate this from wherever you are getting this flag
if(flag.equals("facebook")) {
signIn = context.getBean(FcaebookSignIn.class)
}
else{
signIn = context.getBean(NormalSignIn.class)
}
signIn.signIn(user, request);
}
}