@Autowired for @ModelAttribute

2019-07-20 03:29发布

I'm very new to Spring and I'm encountering the following problem.

I've got the following Controller, in which the @Autowired works perfectly (tried debugging and it works fine).

@Controller
@RequestMapping(value = "/registration")
@SessionAttributes("rf")
public class RegistrationController
{
    @Autowired
    UserJpaDao userDao;

    @RequestMapping(method = RequestMethod.GET)
    @Transactional
    public String setupForm(Model model) throws Exception
    {
        model.addAttribute("rf", new RegistrationForm());
        return "registration";
    }

    @RequestMapping(method = RequestMethod.POST)
    @Transactional
    public String submitForm(@ModelAttribute("rf") RegistrationForm rf, Model model) throws Exception
    {
        // ...

        User user = rf.getUser();
        userDao.save(user);

        // ...

        return "registration";
    }
}

But when I submit my form, the @Autowired field in my RegistrationForm remains null.

RegistrationForm.java:

@Component
public class RegistrationForm
{
    @Autowired
    CountryJpaDao countryDao;

    // ... fields...

    public RegistrationForm()
    {

    }

    @Transactional
    public User getUser() throws InvalidUserDataException
    {
        //...

        Country c = countryDao.findByCode("GB"); // Throws java.lang.NullPointerException

        // ...
    }

    // ... getters/setters...
}

Here is the form's HTML/JSTL:

<form:form method="POST" modelAttribute="rf">
    ...
</form:form>

Can anyone help me?

Thank you.

(inspired by this post on SpringSource forums)

2条回答
smile是对你的礼貌
2楼-- · 2019-07-20 04:14

You're mixing up your concepts here. You use the likes of @Component and @Autowired for Spring-managed beans, and @ModelAttribute for transient, throwaway objects that are used to bind form data. The two should not be mixed. Your @Component and @Autowired annotations on RegistrationForm will be ignored by Spring, because they're not appropriate in that context.

Classes like RegistrationForm should represent the form data, and nothing else. Typically, the controller would ask RegistrationForm for the user ID, and would then look at the actual User object from the DAO itself. If you want RegistrationForm to look up the User itself, then your controller needs to manually supply the DAO to RegistrationForm when it asks for the User object.

As far as that post on the Spring forum is concerned, you'll notice that it never received an answer. It's not a good source to take inspiration from.

Note that I'm not saying that desiring to autowire beans into a form back object is a bad idea, I'm just saying that Spring doesn't do that.

查看更多
爷的心禁止访问
3楼-- · 2019-07-20 04:29

It would work if you use the @Configurable annotation on your model, and this aspectJ configuration on your gradle file:

compileJava << {
    ant.taskdef(
        resource: 'org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties',
        classpath: configurations.compile.asPath)

    ant.iajc(
        inpath: sourceSets.main.output.classesDir.absolutePath,
          classpath: configurations.compile.asPath,
          aspectPath: configurations.aspects.asPath,
          destDir: sourceSets.main.output.classesDir.absolutePath
    )
}

In this way aspectJ will generate code that does the auto wiring.

@Configurable
public class RegistrationForm
{
   ...
}
查看更多
登录 后发表回答