@Autowire出了可以放在属性上,还可以放置的setter方法上以及有参构造方法上,都可以实现Bean的自动装配
@Autowire在Setter方法上 首先给两个实体类增加@Component注解,给User增加一个Address的属性
@Component
public class User {
private String username;
private String password;
private Address address;
public User() {
System.out.println("User 无参数构造方法被调用");
}
public Address getAddress() {
return address;
}
@Autowired
public void setAddress(Address address) {
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + ''' +
", password='" + password + ''' +
", address=" + address +
'}';
}
}
@Component
public class Address {
private Integer id;
private String addressDetail;
public Address() {
System.out.println("Address空参构造方法被调用");
}
public Address(Integer id, String addressDetail) {
System.out.println("Address有参数构造方法被调用");
this.id = id;
this.addressDetail = addressDetail;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddressDetail() {
return addressDetail;
}
public void setAddressDetail(String addressDetail) {
this.addressDetail = addressDetail;
}
@PostConstruct
public void init(){
System.out.println("Address Bean 的初始化方法");
}
@PreDestroy
public void destroy(){
System.out.println("Address Bean的销毁方法");
}
}
在BeanAutoAssembleConfig配置扫描entity包,将User和Address注册到容器中
@ComponentScan(basePackages = {"com.citi.dao","com.citi.service","com.citi.controller","com.citi.entity"})
public class BeanAutoAssembleConfig {
//@Primary
@Bean("personDao2")
public PersonDao personDao(){
return new PersonDao();
}
}
修改BeanAutoAssembleConfigTest,执行测试
public class BeanAutoAssembleConfitTest {
@Test
public void isSameBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
System.out.println("IoC容器初始化完成");
Address address = context.getBean("address",Address.class);
System.out.println(address);
User user = context.getBean("user", User.class);
System.out.println(user.getAddress());
// 关闭容器
((AnnotationConfigApplicationContext)context).close();
}
}
执行测试,控制台打印,Address可以成功注入到User中
@Autowire在有参数的构造方法上 新增加一个只包含Address参数的User构造方法,在方法上面增加@Autowire注解,同时将Setter方法的@Autowire注解注释
@Component
public class User {
private String username;
private String password;
private Address address;
public User() {
System.out.println("User 无参数构造方法被调用");
}
@Autowired
public User(Address address) {
System.out.println("User有参数构造方法被调用");
this.address = address;
}
public Address getAddress() {
return address;
}
//@Autowired
public void setAddress(Address address) {
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + ''' +
", password='" + password + ''' +
", address=" + address +
'}';
}
}
其他地方不用修改,执行测试类,控制台打印如下,可以成功装配Bean,并且是通过调用User的Setter方法实现的
参考@Autowire源码,@Autowire注解可以放在构造方法,setter方法,属性及方法的参数上
修改entity包中的Product实体类,实现ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware接口,并实现接口中的方法
@Component
public class Product implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private Integer id;
private String name;
private Integer price;
private ApplicationContext applicationContext;
@Override
public void setBeanName(String name) {
System.out.println("beanName为:" + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("IoC容器为:" + applicationContext);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String result = resolver.resolveStringValue("操作系统为:${os.name}");
System.out.println(result);
}
// 省略getter/setter/toString方法
}
在config包中增加一个配置类BeanAwareConfig,使用@ComponentScan将entity包中的类注册到容器中
@Configuration
@ComponentScan(value = {"com.citi.entity"})
public class BeanAwareConfig {
}
在test包中增加一个测试类
public class BeanAwareConfigTest {
@Test
public void testAware(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
System.out.println("IoC容器初始化完成");
Product product = context.getBean("product", Product.class);
System.out.println(product);
// 关闭容器
((AnnotationConfigApplicationContext)context).close();
}
}
执行测试,控制台输出如下
控制台输出了IoC容器,beanName等信息,这些都是Spring 底层组件提供的 ,也就是说如果想要把Spring底层的组件注入到自定义的Bean中,需要实现相应的Aware接口,如ApplicationContextAware可以提供IoC容器,这些Aware类都是相关的Processor的后置处理器来处理。