【问题标题】:Abstract class Dependency Injection in Spring MVCSpring MVC 中的抽象类依赖注入
【发布时间】:2017-02-21 05:12:20
【问题描述】:

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

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

如您所见,它将抽象类作为构造函数参数。

我试图从控制器类中检查一些标志,并在此基础上为抽象类分配正确的实现:普通或 facebook 登录。如果没有 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 中的构造函数。如果您需要更多说明,请发表评论。谢谢。

【问题讨论】:

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


【解决方案1】:

您不能创建抽象类的@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
    }
}

然后我强烈建议您为不同类型的登录创建不同的控制器或休息端点

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

【讨论】:

  • 问题似乎出在SignInService 类的构造函数中,我试图将抽象类作为参数传递...你建议如何映射?
  • 在服务类中做和我在控制器类中做的一样的事情,不要在构造函数中传递参数。
猜你喜欢
  • 2011-05-13
  • 2021-09-01
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-10
相关资源
最近更新 更多