隨著spingboot的大火,註解式配置受到了大家的熱烈歡迎,而@Component和@Configuration都可以作為配置類,之前一直都沒覺得這兩個用起來有什麼差別,可能有時程式跑的和自己想的有所區別也沒注意到。
直到看到這篇文章:my.oschina.net/guangshan/blog/1807... 。我意識到@Component和@Configuration是有區別的,錯誤的使用可能會導致嚴重的後果。
請看下面一段程式碼:
@Configuration
public class MyTestConfig {
@Bean
public Driver driver(){
Driver driver = new Driver();
driver.setId(1);
driver.setName("driver");
driver.setCar(car());
return driver;
}
@Bean
public Car car(){
Car car = new Car();
car.setId(1);
car.setName("car");
return car;
}
}
測試程式碼如下
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestApplicationTests {
@Autowired
private Car car;
@Autowired
private Driver driver;
@Test
public void contextLoads() {
boolean result = driver.getCar() == car;
System.out.println(result ? "同一個car" : "不同的car");
}
}
列印結果如下:
同一個car
替換為Component後的列印結果:不同的car
從上面的結果可以發現使用Configuration時在driver和spring容器之中的是同一個物件,而使用Component時是不同的物件。
造成不同結果的原因在ConfigurationClassPostProcessor類之中,透過呼叫enhanceConfigurationClasses方法,為被註解@Configuration的類進行CGLIB代理.
雖然Component註解也會當做配置類,但是並不會為其生成CGLIB代理Class,所以在生成Driver物件時和生成Car物件時呼叫car()方法執行了兩次new操作,所以是不同的物件。當時Configuration註解時,生成當前物件的子類Class,並對方法攔截,第二次呼叫car()方法時直接從BeanFactory之中獲取物件,所以得到的是同一個物件。
本作品採用《CC 協議》,轉載必須註明作者和本文連結