06b84e1a68b1d55a9eab089da5491491141f2380
Spring/Spring Doesn\342\200\231t Recommend @Autowired Anymore.md
| ... | ... | @@ -0,0 +1,113 @@ |
| 1 | +https://medium.com/@dulanjayasandaruwan1998/spring-doesnt-recommend-autowired-anymore-05fc05309dad |
|
| 2 | + |
|
| 3 | +# Spring Doesn’t Recommend @Autowired Anymore | by Dulanjaya Sandaruwan | Medium |
|
| 4 | + |
|
| 5 | + |
|
| 6 | +[Dulanjaya Sandaruwan](https://medium.com/@dulanjayasandaruwan1998) |
|
| 7 | + |
|
| 8 | +In the world of Spring development, particularly Spring Boot, the `@Autowired` annotation has long been a staple for injecting dependencies into Spring-managed beans. However, with the evolution of Spring’s best practices and the introduction of new features, `@Autowired` is no longer the recommended approach for dependency injection. This shift can be surprising for developers familiar with older versions of Spring. In this blog, we'll dive into why `@Autowired` is falling out of favor, the alternatives Spring recommends, and how you can modernize your Spring codebase. |
|
| 9 | + |
|
| 10 | +What is `@Autowired`? |
|
| 11 | +--------------------- |
|
| 12 | + |
|
| 13 | +Before we discuss why Spring no longer recommends `@Autowired`, let's take a quick look at what it does. `@Autowired` is used in Spring to inject dependencies into a class. It can be applied to fields, constructors, and setter methods, letting Spring automatically inject the required bean when your application starts. |
|
| 14 | + |
|
| 15 | +For example: |
|
| 16 | + |
|
| 17 | +``` |
|
| 18 | +@Service |
|
| 19 | +public class MyService { |
|
| 20 | + @Autowired |
|
| 21 | + private MyRepository myRepository; |
|
| 22 | +} |
|
| 23 | +``` |
|
| 24 | + |
|
| 25 | + |
|
| 26 | +In this scenario, Spring injects an instance of `MyRepository` when it creates an instance of `MyService`. |
|
| 27 | + |
|
| 28 | +While this approach works fine, it has some drawbacks, especially in larger, more complex applications. Let’s explore why. |
|
| 29 | + |
|
| 30 | +The Problem with `@Autowired` |
|
| 31 | +----------------------------- |
|
| 32 | + |
|
| 33 | +1. **Hidden Dependencies**: When using `@Autowired` on fields, dependencies are injected behind the scenes, which can lead to hidden dependencies. This practice makes it difficult to know what a class needs to function correctly, complicating testing and debugging. |
|
| 34 | +2. **Immutability Issues**: Field injection allows dependencies to be mutable, making it easier for a class to change them later. This reduces the immutability of your components, which can lead to bugs that are hard to track down. |
|
| 35 | +3. **Testing Difficulties**: Testing components that rely on field injection can be tricky. Since dependencies are not passed through constructors, you need to mock or inject these fields manually in your test setup, which can add unnecessary boilerplate code. |
|
| 36 | +4. **Constructor-Based Injection is Cleaner**: With constructor-based injection, dependencies are explicitly declared in the constructor, making it clear which components are needed for the class to work. This approach makes the class more readable, easier to test, and improves overall maintainability. |
|
| 37 | + |
|
| 38 | +Why Spring Recommends Constructor Injection |
|
| 39 | +------------------------------------------- |
|
| 40 | + |
|
| 41 | +In recent years, the Spring team has shifted toward **constructor injection** as the preferred way of handling dependency injection, moving away from field injection using `@Autowired`. Here are some reasons why: |
|
| 42 | + |
|
| 43 | +**1.Mandatory Dependencies**: Constructor injection forces you to provide all required dependencies when creating an instance of a class. This ensures that the class is always in a valid state, with all its necessary dependencies set at the time of creation. |
|
| 44 | + |
|
| 45 | +``` |
|
| 46 | +@Service |
|
| 47 | +public class MyService { |
|
| 48 | + private final MyRepository myRepository; |
|
| 49 | + public MyService(MyRepository myRepository) { |
|
| 50 | + this.myRepository = myRepository; |
|
| 51 | + } |
|
| 52 | +} |
|
| 53 | +``` |
|
| 54 | + |
|
| 55 | + |
|
| 56 | +In this example, Spring will automatically inject `MyRepository` into the constructor, ensuring that `MyService` is always initialized with a valid repository. |
|
| 57 | + |
|
| 58 | +**2.Immutability**: Constructor injection encourages the use of `final` fields, which enforces immutability. Once a dependency is injected, it cannot be changed, reducing the risk of accidental modification and bugs in the code. |
|
| 59 | + |
|
| 60 | +**3.Improved Testability**: Testing components with constructor injection is much easier. You can simply pass mock dependencies directly into the constructor in your tests, without needing to rely on Spring’s internal wiring. |
|
| 61 | + |
|
| 62 | +**4.No Need for** `**@Autowired**`: If a class has only one constructor, Spring can automatically inject its dependencies without the need for the `@Autowired` annotation. This simplifies the code and reduces annotation clutter. |
|
| 63 | + |
|
| 64 | +The Rise of `@RequiredArgsConstructor` |
|
| 65 | +-------------------------------------- |
|
| 66 | + |
|
| 67 | +For classes that use constructor injection, another helpful tool is Lombok’s `@RequiredArgsConstructor` annotation. This annotation automatically generates a constructor with required fields (i.e., those marked as `final`), further reducing boilerplate code. |
|
| 68 | + |
|
| 69 | +``` |
|
| 70 | +@Service |
|
| 71 | +@RequiredArgsConstructor |
|
| 72 | +public class MyService { |
|
| 73 | + private final MyRepository myRepository; |
|
| 74 | +} |
|
| 75 | +``` |
|
| 76 | + |
|
| 77 | + |
|
| 78 | +With `@RequiredArgsConstructor`, Spring will inject the dependencies without needing to explicitly write the constructor, keeping your code clean and concise. |
|
| 79 | + |
|
| 80 | +`@Autowired` Is Still Useful, But Use it Wisely |
|
| 81 | +----------------------------------------------- |
|
| 82 | + |
|
| 83 | +It’s important to note that `@Autowired` is not deprecated or completely discouraged by Spring. It’s still useful in specific scenarios, such as: |
|
| 84 | + |
|
| 85 | +* **Setter Injection**: In some cases, you may want to use setter injection when dependencies are optional or when you need to inject values after object creation. However, this should be used sparingly and only when necessary. |
|
| 86 | + |
|
| 87 | +``` |
|
| 88 | +@Service |
|
| 89 | +public class MyService { |
|
| 90 | + private MyRepository myRepository; |
|
| 91 | + @Autowired |
|
| 92 | + public void setMyRepository(MyRepository myRepository) { |
|
| 93 | + this.myRepository = myRepository; |
|
| 94 | + } |
|
| 95 | +} |
|
| 96 | +``` |
|
| 97 | + |
|
| 98 | + |
|
| 99 | +* **Legacy Code**: If you’re working on legacy codebases, you’ll likely encounter `@Autowired`. There's no immediate need to refactor all instances of `@Autowired`, but consider transitioning to constructor injection as you update and refactor your code. |
|
| 100 | + |
|
| 101 | +Conclusion: Moving Forward Without `@Autowired` |
|
| 102 | +----------------------------------------------- |
|
| 103 | + |
|
| 104 | +In modern Spring development, constructor injection is considered the best practice for dependency injection, providing cleaner, more maintainable, and testable code. While `@Autowired` is still valid, it’s important to understand its limitations and why Spring recommends moving away from it. |
|
| 105 | + |
|
| 106 | +Here are the key takeaways: |
|
| 107 | + |
|
| 108 | +* Constructor injection promotes immutability and clarity in your code. |
|
| 109 | +* Testing is easier with constructor injection, as you can directly inject mocks or stubs. |
|
| 110 | +* Lombok’s `@RequiredArgsConstructor` simplifies constructor-based dependency injection. |
|
| 111 | +* Use `@Autowired` sparingly, and only when other injection methods are less suitable. |
|
| 112 | + |
|
| 113 | +By embracing these practices, you can write cleaner, more robust Spring applications that are easier to maintain and test over time. |
|
| ... | ... | \ No newline at end of file |