> 文章列表 > Spring之属性填充

Spring之属性填充

Spring之属性填充

Spring给属性的方式一般有三种

1、通过在属性的添加@Autowired注解

@Component
public class UserService {@Autowiredprivate OrderService orderService;public void setOrderService(OrderService orderService) {this.orderService = orderService;}public OrderService getOrderService() {return this.orderService;}
}

1、Spring在属性填充的时候,用org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessPropertyValues将类中属性使用@Autowired注解的属性查找出来。
2、同时在查找完成之后就会立刻赋值

2、通过@Bean(autowire= Autowire.BY_NAME)

@Component
public class UserService {private OrderService orderService;public void setOrderService(OrderService orderService) {this.orderService = orderService;}public OrderService getOrderService() {return this.orderService;}
}public class OrderService {
}@ComponentScan("com.wwh")
public class AppConfig {@Bean(autowire= Autowire.BY_NAME)public OrderService orderService() {return new OrderService();}
}

1、这种方式可以不需要在private OrderService orderService上添加属性;
2、但是必须得有setOrderService方法;
3、在定义OrderService这个Bean的时候需要使用@Bean(autowire= Autowire.BY_NAME);
4、@Bean(autowire= Autowire.BY_NAME)表示通过名字添加。
5、BY_NAME使用的是setOrderService方法的OrderService,将首字母小写,开始查找Bean或者创建Bean。
6、通过这种方式会过滤掉简单类型,比如Enum、CharSequence、八大基本类型等等,即使向单例池中注册了Bean,获取的值也会是null。

通过这种方法添加属性的源码

protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {// 获取属性字段的名称String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {// 判断是否有这个属性字段对应的Bean或者BeanDefinfitionif (containsBean(propertyName)) {// 创建Bean或者从单例池中获取字段对应的BeanObject bean = getBean(propertyName);pvs.add(propertyName, bean);// 绑定Bean与属性对应Bean的关系registerDependentBean(propertyName, beanName);if (logger.isTraceEnabled()) {logger.trace("Added autowiring by name from bean name '" + beanName +"' via property '" + propertyName + "' to bean named '" + propertyName + "'");}}else {if (logger.isTraceEnabled()) {logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +"' by name: no matching bean found");}}}}

这个方法主要是通过BY_NAME找出有多少个属性需要被填充值。

3、通过@Bean(autowire= Autowire.BY_TYPE)

@Component
public class UserService {private OrderService orderService;public void setOrderService(OrderService orderService) {this.orderService = orderService;}public OrderService getOrderService() {return this.orderService;}
}public class OrderService {
}@ComponentScan("com.wwh")
public class AppConfig {@Bean(autowire= Autowire.BY_TYPE)public OrderService orderService() {return new OrderService();}
}

1、这种方式可以不需要在private OrderService orderService上添加属性;
2、但是必须得有setOrderService方法;
3、在定义OrderService这个Bean的时候需要使用@Bean(autowire= Autowire.BY_TYPE);
4、@Bean(autowire= Autowire.BY_TYPE)表示通过名字添加。
5、BY_TYPE使用的是setOrderService方法的参数,通过将参数查找出来,创建Bean或者从单例池中把对象找出赋值。
6、通过这种方式会过滤掉简单类型,比如Enum、CharSequence、八大基本类型等等,即使向单例池中注册了Bean,获取的值也会是null。

通过这种方法添加属性的源码

protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}Set<String> autowiredBeanNames = new LinkedHashSet<>(4);// 获取属性字段的名称String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {// 获取属性字段描述器PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);// Don't try autowiring by type for type Object: never makes sense,// even if it technically is a unsatisfied, non-simple property.if (Object.class != pd.getPropertyType()) {// 获取set方法里的参数MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);// 获得参数的描述器DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);// 获得参数的值Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {// 属性填充registerDependentBean(autowiredBeanName, beanName);if (logger.isTraceEnabled()) {logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +propertyName + "' to bean named '" + autowiredBeanName + "'");}}autowiredBeanNames.clear();}}catch (BeansException ex) {throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);}}}

4、三种赋值的对比。

1、在Spring源码中,第一种会在查找出来属性之后立刻赋值,第二种和第三种则是需要在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues这个方法中被复制。
2、假如实现了MergedBeanDefinitionPostProcessor接口,手动给这个属性赋值,最终orderService将会是用户自己设定的值。

@Component
public class SpringTestBeanPostProcessor implements MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanName.equals("userService")) {MutablePropertyValues propertyValues = new MutablePropertyValues();OrderService orderService = new OrderService();System.out.println("beanPostProcessor: "+orderService);propertyValues.addPropertyValue("orderService", orderService);beanDefinition.setPropertyValues(propertyValues);}}@Overridepublic void resetBeanDefinition(String beanName) {MergedBeanDefinitionPostProcessor.super.resetBeanDefinition(beanName);}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
OrderService orderService = (OrderService) applicationContext.getBean("orderService");
System.out.println("UserService OrderService: "+userService.getOrderService());
System.out.println("OrderService: "+orderService);

Spring之属性填充