xml中定义Bean,程序员手动给某个属性赋值。
<bean name="userService" class="com.firechou.service.UserService">
<property name="orderService" ref="orderService"/>
</bean>
<bean name="userService" class="com.firechou.service.UserService">
<constructor-arg index="0" ref="orderService"/>
</bean>
<bean id="userService" class="com.firechou.service.UserService" autowire="byType"/>
Spring会自动的给userService中所有的属性自动赋值(不需要这个属性上有@Autowired注解,但需要这个属性有对应的set方法);
XML的自动注入底层其实也就是set方法注入和构造方法注入;
Bean的自动注入模式autowire:
获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean,如果找到多个,会报错。
找到所有set方法所对应的XXX部分的名字,根据XXX部分的名字去获取bean。
通过构造方法注入,可以不写set方法;
如果存在多个构造方法,则通过构造方法推断来选择某个构造方法;
Spring利用构造方法的参数信息从Spring容器中去找Bean,找到Bean之后作为参数传给构造方法,从而实例化得到一个bean对象,并完成属性赋值(属性赋值的代码得程序员来写);
关闭autowire
PropertyDescriptor:
创建Bean的过程中,填充属性时,Spring会去解析当前类,解析类中每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor中有几个属性:
什么是set和get方法:
方法参数个数为0个,并且方法名字以"get"开头,或者方法名字以"is"开头并且方法的返回类型为boolean
方法参数个数为1个,并且方法名字以"set"开头并且方法返回类型为void
@Autowired注解相当于XML中的autowire属性的注解方式的替代;
@Autowired注解提供了与XML中autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性;
XML中的autowire控制的是整个bean的所有属性,而@Autowired注解是直接写在某个属性、某个set方法、某个构造方法上的;
如果一个类有多个构造方法,那么如果用XML的autowire=constructor,无法控制到底用哪个构造方法,可以用@Autowired注解来直接指定想用哪个构造方法;
@Autowired注解还可以控制,哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制;
@Autowired无法区分byType和byName,@Autowired是先byType,如果找到多个则byName;
@Autowired注解可以写在:
在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor的**postProcessMergedBeanDefinition()**找出注入点并缓存。
找注入点的流程为:
Spring在AutowiredAnnotationBeanPostProcessor的**postProcessProperties()**方法中,会遍历所找到的注入点依次进行注入。
字段注入:
Set方法注入:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// 根据DependencyDescriptor依赖描述从BeanFactory中找出对应的唯一的一个Bean对象。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
}
}
javax.inject.Provider
类对象,则返回Jsr330Provider对象doResolveDependency(descriptor)
。或这,直接生成一个ObjectFactory对象,在调用ObjectFactory的getObject方法时调用调用doResolveDependency(descriptor)
根据类型找beanName。
java中的泛型:java.lang.reflect.Type
通过反射获取字段类型,分为:
示例:
public class ParameterizedTypeTest<T> {
private int i;
private Integer it;
private int[] iarray;
private List list;
private List<String> slist;
private List<T> tlist;
private T t;
private T[] tarray;
public static void main(String[] args) throws NoSuchFieldException {
test(ParameterizedTypeTest.class.getDeclaredField("i"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("it"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("iarray"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("list"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("slist"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("tlist"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("t"));
System.out.println("=======");
test(ParameterizedTypeTest.class.getDeclaredField("tarray"));
}
public static void test(Field field) {
if (field.getType().isPrimitive()) {
System.out.println(field.getName() + "是基本数据类型");
} else {
System.out.println(field.getName() + "不是基本数据类型");
}
if (field.getGenericType() instanceof ParameterizedType) {
System.out.println(field.getName() + "是泛型类型");
} else {
System.out.println(field.getName() + "不是泛型类型");
}
if (field.getType().isArray()) {
System.out.println(field.getName() + "是普通数组");
} else {
System.out.println(field.getName() + "不是普通数组");
}
if (field.getGenericType() instanceof GenericArrayType) {
System.out.println(field.getName() + "是泛型数组");
} else {
System.out.println(field.getName() + "不是泛型数组");
}
if (field.getGenericType() instanceof TypeVariable) {
System.out.println(field.getName() + "是泛型变量");
} else {
System.out.println(field.getName() + "不是泛型变量");
}
}
}
结果:
i是基本数据类型
i不是泛型类型
i不是普通数组
i不是泛型数组
i不是泛型变量
=======
it不是基本数据类型
it不是泛型类型
it不是普通数组
it不是泛型数组
it不是泛型变量
=======
iarray不是基本数据类型
iarray不是泛型类型
iarray是普通数组
iarray不是泛型数组
iarray不是泛型变量
=======
list不是基本数据类型
list不是泛型类型
list不是普通数组
list不是泛型数组
list不是泛型变量
=======
slist不是基本数据类型
slist是泛型类型
slist不是普通数组
slist不是泛型数组
slist不是泛型变量
=======
tlist不是基本数据类型
tlist是泛型类型
tlist不是普通数组
tlist不是泛型数组
tlist不是泛型变量
=======
t不是基本数据类型
t不是泛型类型
t不是普通数组
t不是泛型数组
t是泛型变量
=======
tarray不是基本数据类型
tarray不是泛型类型
tarray是普通数组
tarray是泛型数组
tarray不是泛型变量
Spring中注入点为泛型时:
@Component
public class UserService extends BaseService<OrderService, StockService> {
public void test() {
System.out.println(o);
}
}
public class BaseService<O, S> {
@Autowired
protected O o;
@Autowired
protected S s;
}
userService.getClass().getGenericSuperclass().getTypeName()
获取到具体的泛型信息,比如com.firechou.service.BaseService
for (TypeVariable extends Class>> typeParameter : userService.getClass().getSuperclass().getTypeParameters()) {
System._out_.println(typeParameter.getName());
}
oField.getGenericType()
就知道当前field使用的是哪个泛型,就能知道具体类型了