当前位置: 动力学知识库 > 问答 > 编程问答 >

java - Placement of @Autowired annotation

问题描述:

I've seen the @Autowired annotation placed just before the constructor of a POJO used as controller.

@Controller

public class LoginController{

private UsuarioService usuarioService;

@Autowired

public void LoginController(UsuarioService usuarioService){

this.usuarioService = usuarioService;

}

// More code

}

This constructor takes as argument the reference to the object we want Spring to inject.However if I place this annotation just before the property declaration the application works just the same.

@Controller

public class LoginController{

@Autowired

private UsuarioService usuarioService;

// More code

}

My question is what is the difference between this two approaches in terms of pros and cons.

网友答案:

My advice to you would be to never use @Autowired on fields (except in Spring @Configuration classes).

The reason is very simple: TESTING!!!!

When you use @Autowired on fields of a class, then that class becomes harder to unit test because you cannot easily use your own (possible mocked) dependencies for the class under test. When you use constructor injection then is becomes immediately evident what the dependencies of the class are, and creating that class becomes straight forward (simple constructor call).

Some points that need to made:

1) Some might argue that even when @Autowired is used the class can still be unit tested with the use of Mockito's @InjectMocks, or Spring's ReflectionTestUtils.setField, but my opinion is that the creation of a unit under test should be as dead simple as possible.

2) Another point that could be mentioned is that there might be many arguments in the constructor making the manual invocation of the constructor (either in the test or elsewhere) difficult. This however is not a problem regarding the creation of the class, but a problem in the design. When a class has to many dependencies, in most cases it is trying to do too much and needs to broken into smaller classes with fewer dependencies.

网友答案:

@Autowired annotation on setter methods is to get rid of the element in XML configuration file. When Spring finds an @Autowired annotation used with setter methods, it tries to perform byType autowiring on the method

@Autowired annotation on properties is to get rid of the setter methods. When you will pass values of autowired properties using Spring will automatically assign those properties with the passed values or references.

Here is an example of both the usage:

http://www.tutorialspoint.com/spring/spring_autowired_annotation.htm

网友答案:

This Springsource blog post mentions that constructor injection makes it easy to validate required dependencies, if used in combination with contructors assertions that are good practice anyway and would also work if the class is instantiated outside Spring with the new operator:

@Controller
public class LoginController{

    private UsuarioService usuarioService;

    @Autowired
    public void LoginController(UsuarioService usuarioService){
        if (usuarioService == null) {
            throw new IllegalArgumentException("usuarioService cannot be null.");
        }
        this.usuarioService = usuarioService;
    }
}

This type of assertions are general best practice that is advised to do independently of the class being a Spring bean or not.

For setter or property injection there is also the @Required annotation for validating missing dependencies or @Autowired(required = true). According to the blog post, constructor injection provides this advantage, but for historical reasons setter injection is more frequently used in Spring.

分享给朋友:
您可能感兴趣的文章:
随机阅读: