Spring MVC中的抽象类依赖注入

时间:2017-02-21 05:12:21

标签: spring spring-mvc dependency-injection abstract-class autowired

我有一个用于登录功能的抽象类

@Component
public abstract class SignIn {    

    public abstract LogInOperationToken signin(User user, HttpServletRequest request);


}

由两个具体的类FacebookSignInImplNormalSignInImpl实现,它们也被注释为@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中的构造函数。如果您需要进一步澄清,请发表评论。感谢。

1 个答案:

答案 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);
    }
}