spring的依赖注意之@Autowired注解
来继续描述一下属性描述器:PropertyDescriptor
可以去看一下属性描述器中的最基本的属性,是由原生的jdk自带的类,来描述java中的一个类的基本属性的操作,在spring中通过属性描述器来找到对应的属性,也就是说利用这个类来找到对应的get/set/ter方法,然后将get或者是get方法去掉之后,spring认为这就是类中的属性,那么就需要来进行注入。
// 对应的就是去掉set方法之后的属性;
private String baseName;
// 对应的就是set方法
private String writeMethodName;
// 对应的就是get方法
private String readMethodName;
在AbstractAutowireCapableBeanFactory.unsatisfiedNonSimpleProperties方法上打上断点,看一下for循环中的值:
可以看到属性描述器中包含了对应类中的get/set方法来进行读取到对应的属性(即使类中没有对应的set/get方法)
所以这种使用方式不满足java中的bean的定义,所以我觉得这种BY_TYPE和BY_NAME方式也是被弃用的最大原因。
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
// 这里需要注意到两个点:
// 1、pd.getWriteMethod():只要set方法,不要get方法
// 2、!pvs.contains(pd.getName()),如果之前操作过bean定义给属性赋值了,那么这里就不会来进行赋值了
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName())
// 简单类型,对于BY_TPYE和BY_NAME来说,是不管的;但是对于@Autowired来说,是需要管理的
&& !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
这里只会来找类中的set方法,所以对于这种BY_TYPE和BY_NAME方式来说,最大的依赖便是依赖于其中的set方法
假如说要是找到了对应的对应的set方法,接下来就是根据对应的属性名称去容器中去找bean
针对BY_TYPE方式:
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);
// 找到对应的类型对应的bean
// 这个方法在@Autowired中也使用到了,所以这个重点关注一下
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);
}
}
下面来看下对应的BY_NAME方式:
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 找到了对应的set方法对应的属性之后,然后进行循环,对bean中的属性来进行注入
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 获取得到名字之后,直接通过getBean方法来进行从容器中来进行获取得到bean中的属性
Object bean = getBean(propertyName);
// 得到之后,并没有立即进行填充,这里只是做了一个bean的赋值。所以这里没有进行真正的赋值
// 而@Autowired注解则是直接通过反射来进行set的操作
pvs.add(propertyName, bean);
// 来注册依赖的bean的名称,这里也就是之前的propertyName被beanName给依赖了
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");
}
}
}
}
下面来尝试一下上面的使用过程,下面使用注解版来测试上面的过程:
配置类:
@ComponentScan(basePackages = "com.guang.spring.demo6")
public class Demo6Config {
@Bean(autowire = Autowire.BY_TYPE)
public User user(){
return new User();
}
@Bean(autowire = Autowire.BY_TYPE)
public UserService userService(){
return new UserService();
}
@Bean
public Number number(){
return 666;
}
}
看一下对应的UserService
public class UserService {
private User user;
private Number number;
public void setNumber(Number number) {
this.number = number;
}
public void setUser(User user) {
this.user = user;
}
public void test(){
System.out.println(user);
System.out.println(number);
}
}
进行测试:
public class Demo6Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Demo6Config.class);
UserService userService = context.getBean(UserService.class);
userService.test();
}
}
看下打印:
com.guang.spring.demo6.user.bean.User@587c290d
null
因为Number对其来说是属于简单类型的,所以这里不会来进行赋值。
那么如果是使用@Auwired注解来进行尝试:
首先将配置类来进行修改:
@ComponentScan(basePackages = "com.guang.spring.demo6")
public class Demo6Config {
@Bean // (autowire = Autowire.BY_TYPE)
public User user(){
return new User();
}
@Bean // (autowire = Autowire.BY_TYPE)
public UserService userService(){
return new UserService();
}
@Bean
public Number number(){
return 666;
}
}
然后修改userservice:
public class UserService {
@Autowired
private User user;
@Autowired
private Number number;
public void setNumber(Number number) {
this.number = number;
}
public void setUser(User user) {
this.user = user;
}
public void test(){
System.out.println(user);
System.out.println(number);
}
}
然后再次来进行打印:
com.guang.spring.demo6.user.bean.User@306279ee
666
所以这里总结出来:BY_NAME和BY_TYPE的使用是和@Autowired注解是有区别的,至少在简单类型上@Autowired会来进行注入,而BY的方式不会来进行注入。
上面的BY的方式只是来做一个依赖依赖,具体的是在填充属性的操作是在AbstractAutowireCapableBeanFactory.populateBean的最后一步来进行的操作:
if (pvs != null) {
// 将依赖的bean真正的进行设置
applyPropertyValues(beanName, mbd, bw, pvs);
}
在下面接着使用@Autowired注解来进行注入对应的值,这里是通过后置处理器来进行处理的:
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
AutowiredAnnotationBeanPostProcessor.postProcessProperties来处理@Autowired注解和@Value注解的;
CommonAnnotationBeanPostProcessor.postProcessProperties来处理@Resource注解的;
下面来看下对应的AutowiredAnnotationBeanPostProcessor中的方法
对于每个bean来说,在整个生命周期过程中都将回来执行postProcessMergedBeanDefinition,然后是postProcessProperties,那么看下解决@Autowired注解中的值:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 通过方法名称可以开电脑找到@Autowired注解对应的注入点信息,整个只是找到对应的注入点信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
然后进入到对应的方法中来:
metadata = buildAutowiringMetadata(clazz);
来找到@Autowired注解标注的一些源信息,找到对应的注入点,然后加入到缓存中来:
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 什么时候一个类不需要来找对应的注入点。过滤掉
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 找字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// 不要static关键字修饰的
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
// 属性的注入点
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 找方法。根据方法的参数类型和参数名称来找到对应的方法来从容器中来进行获取得到对应的bean进行缓存
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 桥接方法,针对的是字节码层面上的泛型。这里是要用来找到被桥接的方法
// 处理桥接方法的情况!可以简单理解成找到原始的加了@Autowired的方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 方法的注入点
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
// 在添加disposal方法的时候也会有这样的操作
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
看一下对字段来说是符合来进行操作的:
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 是否有@Autowired、@Value和@Inject注解
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// @Autowired注解中的require属性
boolean required = determineRequiredStatus(ann);
// 不为空,那么加入到字段集合中来。这里存的都是注入点
// 属性的注入点
currElements.add(new AutowiredFieldElement(field, required));
}
});
首先来找到对应的注解:
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
// 然后来进行遍历
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
// 如果有对应的注解,那么来进行获取得到对应的值即可
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
所以在这里看到了autowiredAnnotationTypes,那么看下这里的是如何来进行赋值的
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
在构造方法中来进行赋值操作。
将方法这块拎出来单独操作:
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 是否是桥接方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 过滤掉static关键字修饰的方法
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// 如果被标注了@Autowred注解,但是方法上是没有参数的,那么也会是一个注入点
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
// 检查@Autowired注解对应的值
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 方法的注入点
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
上面的类似下面这种操作:
@Autowired
public void sayHello(){
System.out.println("hello,world");
}
在bean的属性注入阶段,也会来进行执行。
上面整体的逻辑是在寻找注入点,这阶段只是对应的寻找过程而已,而不是真正的来进行执行。
不需要寻找注入点的过程:
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
if (annotationName.startsWith("java.")) {
return true;
}
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
return (type.getName().startsWith("java.") || type == Ordered.class);
}
注解开头不是以java.开头的,直接返回true;如果对应的class的开头是以java.开头的或者是Ordered的类型的,那么返回FALSE;
最终返回true。所以不需要进行注入点的是第二个判断。
找完了对应的注入点之后,会先来保存起来:
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
return (elements.isEmpty() ? new InjectionMetadata(clazz, Collections.emptyList()) :
new InjectionMetadata(clazz, elements));
}
最终返回到这一步,注意一下,这里有一步缓存操作:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
然后进行检查注入点:
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
for (InjectedElement element : this.injectedElements) {
Member member = element.getMember();
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
beanDefinition.registerExternallyManagedConfigMember(member);
checkedElements.add(element);
}
}
this.checkedElements = checkedElements;
}
然后这步执行完成之后来到下面的属性赋值阶段:
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 找到对应的属性对应点,然后开始来进行注入阶段。看到了这里的PVS
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 开始来进行赋值
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
看下对应的阶段流程:InjectionMetadata.inject方法
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
// 这里开始来进行遍历!因为前面分为了方法和属性,所以这里需要来进行分类
element.inject(target, beanName, pvs);
}
}
}
找下对应的方法,但是这个方法是用来处理@Resource注解的,不是来处理@Autowired的
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
// 检查是否需要来进行跳过!这里和之前的处理bean定义的那块来进行设置属性这块是相关的。
// 如果说在后置处理阶段已经进行了赋值,那么在这里将会来选择进行跳过;如果没有,这里将会来进行赋值
if (checkPropertySkipping(pvs)) {
return;
}
try {
// 反射来进行赋值
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
所以处理@Autowired的应该来看对应的子类中的方法,分为两个:使用@Autowired注解的属性和@Autowired注解的方法
那么小结一下:
先去调用postProcessMergedBeanDefinition来寻找对应的注入点,然后执行postProcessProperties方法来找到对应的属性来进行判断是否需要来进行注入。
那么上面看到了找到了对应的注入点,下面来看看到底是如何来进行注入的。
直接进入到对应的注入点中来:
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
然后看下对应的注入点,注意这个方法是用来注入对应的@Resource注解的:
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
如果是使用了@Autowired注入的方法和属性,这里应该查看其子类:
AutowiredFieldElement.inject和AutowiredMethodElement的注解
所以来看下字段和方法分别是怎么来进行注入的?
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
// 找到字段对应的值
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
// 找到了之后,通过反射来进行注入
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
看下对应的方法:
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
// 依赖描述器 这里封装的是字段
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
// 设置对应的类型
desc.setContainingClass(bean.getClass());
// 看上去像是bean的名称
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
// 类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
// 开始来尝试进行解析对应的值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
那么看看是如何来进行解析的:
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 在jdk8中想要拿到属性的值,需要引入其他的方式,从字节码层面上来进行获取得到即可;
// 解析到真正的名称。不然解析出来的还是arg0、arg1、arg2等,这里是基于本地变量表的方式来进行获取;
// 这里是初始化参数名称的发现器
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 判断依赖的类型
// 这里判断的是方法参数的类型
if (Optional.class == descriptor.getDependencyType()) {
// 如果是
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 99的情况下都是这种类型
// 判断属性/set方法上有没有添加@Lazy注解
// 注:如果@Autowired注解+@Lazy加在属性上,那么将会产生一个代理对象
// 如果没有@Lazy注解,那么就直接返回了
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
来看下怎么判断@Autowired注解或者是属性上是否添加了@Lazy注解的
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
// 为true的时候,会产生代理对象
return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}
protected boolean isLazy(DependencyDescriptor descriptor) {
// 判断属性上是否有@Lazy注解
// 获取得到所有的注解判断是否有对应的@Lazy注解
for (Annotation ann : descriptor.getAnnotations()) {
Lazy lazy = AnnotationUtils.getAnnotation(ann, Lazy.class);
if (lazy != null && lazy.value()) {
// 有的话返回true
return true;
}
}
// 这里判断的是方法上是否有对应的注解
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
Method method = methodParam.getMethod();
// 如果方法返回值为void并且method为null,回来执行下面的方法?????
if (method == null || void.class == method.getReturnType()) {
Lazy lazy = AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);
if (lazy != null && lazy.value()) {
return true;
}
}
}
return false;
}
那么这段代码描述的信息如下所示,看下对应的代码显示:
public class UserService {
@Autowired
@Lazy
private User user;
@Autowired
private Number number;
@Autowired
public void setNumber(@Lazy Number number) {
this.number = number;
}
public void testOne(){
System.out.println(user.a());
}
}
也就是说set方法上和属性上有@Autowired注解+@Lazy注解,产生的是一个代理对象,只有在真正使用的时候才会来调用真正的真正的bean工厂的对象来进行调用。
比如说在属性注入阶段,对于User属性来说,此时是一个代理对象,在user.a()的时候才会从bean工厂中来获取得到真正的对象来调用a()方法。这就是@Lazy延迟的一个效果。
来写个代码来进行测试:
@Component
public class OrderService {
public void test(){
System.out.println("当前的orderService对应的对象是:"+this);
}
}
@Component
public class UserService {
@Autowired
@Lazy
private OrderService orderService;
public void test(){
System.out.println("UserService中的orderService是:"+orderService);
// 这里会来真正的调用这里的方法
orderService.test();
}
}
然后来编写测试类:
public class Demo7Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Demo7Config.class);
UserService userService = context.getBean(UserService.class);
userService.test();
}
}
打印输出:
UserService中的orderService是:com.guang.spring.demo7.order.service.OrderService@7a52f2a2
当前的orderService对应的对象是:com.guang.spring.demo7.order.service.OrderService@7a52f2a2
结果发现二者都是一样的,那么打上断点看看中间的bean的状态显示,但是这里的代理对象是看不到的。
不知道如何来进行查看。说一下使用过程,这里会在循环阶段阶段使用到@Lazy注解
那么如果是没有@Lazy注解的,接下来将会走另外一段逻辑:
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 找到对应的注解点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 下面这段逻辑是用来处理@Value注解的,说明了什么?对于字段和方法前面都可以写@Value属性
Class<?> type = descriptor.getDependencyType();
// 开始来找对应的@Value注解的值开始来进行解析
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
// 这里是99%的情况都是这个步骤
if (value instanceof String) {
// 进行占位符填充,也就是($())这种情况,对应的就是enviremont对象,也就是环境变量
// 可以从properties中来获取得到其中的value,这里的为key
// 这里是从环境变量对象中来进行获取得到对应的值的;
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析@Value("#{xxx}") 这种表达式
// 这种书写方式表示的是去容器中找到名字叫做xxx的bean对象然后给当前属性来进行赋值
value = evaluateBeanDefinitionString(strVal, bd);
}
// 将value转换成对应的类型,来进行转换的功能而已
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
看下@Value来拿对应的值的情况:
// 传入进来的依赖描述器中可能是属性,也可能是方法对象,所以会分为两种情况来进行讨论
public Object getSuggestedValue(DependencyDescriptor descriptor) {
// 获取得到属性的值
Object value = findValue(descriptor.getAnnotations());
if (value == null) {
// 获取得到方法额值
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
value = findValue(methodParam.getMethodAnnotations());
}
}
return value;
}
这里也来演示一下对应的案例:
@ComponentScan(basePackages = "com.guang.spring.demo7")
// 引入配置文件
@PropertySource(value = "demo7.properties" )
public class Demo7Config {
}
对应的类:
@Component
public class User {
@Value("${name}")
private String name;
public void test(){
System.out.println("当前对象中的user.name是:"+name);
}
}
对应的properties文件:
name=guang
测试打印:
当前对象中的user.name是:guang
但是如果@Value注解写的不是这里的值,而是一个找不到的值,那么将会打印出来属性填充的值:
@Component
public class User {
@Value("${name1}")
private String name;
public void test(){
System.out.println("当前对象中的user.name是:"+name);
}
}
那么控制台打印出来的值如下所示:
当前对象中的user.name是:${name1}
也就是没有找到,属性填充的就是上面的值
那么如果properties文件中没有对应的值,接下来通过环境变量对象Envirment对象中来进行获取得到对应的值:
也可以在java命令中带上-D的命令来进行执行,方便我们在外界来进行修改
使用@Value("#{xxx}")来进行测试:这种方式就代表着要去容器中找一个xxx的bean,然后赋值给bean中的一个属性
@Component
public class Dog {}
@Component
public class DogService {
@Value("#{dog}")
private Dog dog;
public void test(){
System.out.println("dogservice中的dog为:"+dog);
}
}
测试类:
Dog dog = context.getBean(Dog.class);
System.out.println("容器中的dog的值是:"+dog);
DogService dogService = context.getBean(DogService.class);
dogService.test();
看控制台的打印输出:
容器中的dog的值是:com.guang.spring.demo7.animal.bean.Dog@12b0404f
dogservice中的dog为:com.guang.spring.demo7.animal.bean.Dog@12b0404f
@Value还有另外一种用法
@Value("guang")
private String name;
书写一个案例来进行测试一下:
@Component
public class Cat {
@Value("dog")
private String name;
public void test(){
System.out.println("name为:"+name);
}
}
那么这种方式也是可以给Cat中的name属性来进行赋值的。
这里背后设计的原理:找到对应的值,然后转换成对应的类型,如果有对象类型的转换器,那么就可以来进行转换:
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
如果找到了,那么就可以来进行赋值了。所以这里有可类型转换器,那么我们也可以自己来进行定义对应的类型转换器到容器中去,然后来进行赋值。
依赖注入阶段只要是@Autowired、@Inject或者是@Value注解,那么都将会是一个注入点,如果找到了,那么直接进行返回。
如果没有@Value注解,那么将会来执行下面的操作:对应的最常见的也就是@Autowired注解,首先根据类型来进行查找,如果找到了多个,那么根据名称来进行查找,那么这块的实现逻辑是怎样的?下面也会来进行实现,首先来看一下一个例子:
public interface Tuling { }
@Component
public class Company implements Tuling {}
@Component
public class Employ implements Tuling {
@Autowired
private List<Tuling> tulingList;
public void test(){
// 这里只会来打印出来一个!那么另外的几个?
System.out.println("tuling对应的类型有:"+tulingList);
}
}
@Component
public class Worker {
@Autowired
private List<Tuling> tulingList;
public void test(){
// 这里只会来打印出来一个!那么另外的几个?
System.out.println("tuling对应的类型有:"+tulingList);
}
}
测试类:
context.getBean(Employ.class).test();
context.getBean(Worker.class).test();
打印:
tuling对应的类型有:[com.guang.spring.demo7.tuling.Company@1ee807c6]
tuling对应的类型有:[com.guang.spring.demo7.tuling.Company@1ee807c6, com.guang.spring.demo7.tuling.Employ@76a4d6c]
可以看到在本类中来打印,对应的信息是不全的;但是在其他类中来打印,确是全的。
再来新增一个来进行测试:
@Component
public class Worker {
@Autowired
private List<Tuling> tulingList;
@Autowired
private Map<String,Tuling> tulingMap;
public void test(){
// 这里只会来打印出来一个!那么另外的几个?
System.out.println("tuling对应的类型有:"+tulingList);
System.out.println(tulingMap);
}
}
那么看下打印:
tuling对应的类型有:[com.guang.spring.demo7.tuling.Company@1ee807c6]
tuling对应的类型有:[com.guang.spring.demo7.tuling.Company@1ee807c6, com.guang.spring.demo7.tuling.Employ@76a4d6c]
{company=com.guang.spring.demo7.tuling.Company@1ee807c6, employ=com.guang.spring.demo7.tuling.Employ@76a4d6c}
其中对于map来说,key一定要是String类型的,存的是bean的名称
DefaultListableBeanFactory.doResolveDependency中来对上上面的过程中来进行处理:
先来处理Map、List、数组类型等其他类型的
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
如果属性不是上面的类型,而是正常的类型,下面将会来走下面的步骤:
// 需要注意的是这里的Object有两种情况,一种是class,另外一种就是bean;
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果匹配到了多个
if (matchingBeans.size() > 1) {
// 这里会来进行筛选
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
// 也可能是筛选之后一个都没有
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
// 匹配到了一个
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
如果得到了多个bean,来看下是如何来进行筛选的:
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 是否有@Primary注解优先的,如果有,优先选择这个
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
// 通过byName的方式来进行注入
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
来测试一下:
@Component
public class Nuddle {}
@ComponentScan(basePackages = "com.guang.spring.demo7")
@PropertySource(value = "demo7.properties" )
public class Demo7Config {
@Bean
public Nuddle nuddle2(){
return new Nuddle();
}
}
@Component
public class OrderService {
@Autowired
private Nuddle nuddle1;
public void test(){
System.out.println("当前的orderService对应的对象是:"+this);
}
}
这样子会报错,因为两个bean的名字是nuddle1和nuddle2,在进行属性注入的时候,发现找到了多个,然后通过名称来进行注入,发现名字也不一样,所以直接报错。
报错信息:
No qualifying bean of type 'com.guang.spring.demo7.mian.Nuddle' available: expected single matching bean but found 2: nuddle,nuddle2
解决方式一:那么只需要来修改属性注意的属性的名称即可。
解决方式二:使用@Primary注解
@ComponentScan(basePackages = "com.guang.spring.demo7")
@PropertySource(value = "demo7.properties" )
public class Demo7Config {
@Bean
@Primary
public Nuddle nuddle2(){
Nuddle nuddle = new Nuddle();
System.out.println("nuddle2的值是:"+nuddle);
return nuddle;
}
}
再次来尝试上面的操作,就会发现也解决了这个问题。
判断完成之后,如果没有发现@Primary注解,那么也不会来通过BY_NAME的方式来进行查找,而是通过优先级方式来进行查找:
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
下面来查看一下如何来进行查找的:
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance != null) {
// 获取得到对应的接口来进行判断
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
// 获取得到优先级高的属性的名称进行返回
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
}
return highestPriorityBeanName;
}
查看一下对应的接口:
protected Integer getPriority(Object beanInstance) {
Comparator<Object> comparator = getDependencyComparator();
if (comparator instanceof OrderComparator) {
return ((OrderComparator) comparator).getPriority(beanInstance);
}
return null;
}
看看是否实现了OrderComparator接口,如果实现了,那么调用对应的getPriority方法来返回对应的优先级的值。
如果查询出来的是多个bean,所以这里的步骤是:1、@Primary注解;2、优先级(@Priority注解等指定);3、name;
那么再次回到上面:DefaultListableBeanFactory.
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
这里的Object分为了两种情况:1、class;2、bean对象;
为什么是class?因为这里通过bean定义也可以获取得到其中的beanName来进行判断。
然后如果是class:
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
那么看下spring是如何通过类型去找到对应的bean的
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
看下源码:
// requiredType类型对应的是bean的名称
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
根据类型去找bean目前来说:1、bean定义中是有的;2、单例池中肯定也是有的;
public static String[] beanNamesForTypeIncludingAncestors(
ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
Assert.notNull(lbf, "ListableBeanFactory must not be null");
String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
if (lbf instanceof HierarchicalBeanFactory) {
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
String[] parentResult = beanNamesForTypeIncludingAncestors(
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
result = mergeNamesWithParent(result, parentResult, hbf);
}
}
return result;
}
这段代码再来进行描述的时候,从当前工厂和父类工厂中来进行查找,然后最终合并beanName,二者逻辑是一样的,所以随便看一下即可:
// 注意includeNonSingletons这个参数,是否包含非单例的bean
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
// 这里是获取得到所有类型(单例、多例)的bean还是单例的bean?
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
// 上面做一些缓存,真正的是从这里开始的
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
所以进入到方法中去之后,首先看到一个for循环:
// 获取得到所有的bean的名称
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name is not defined as alias for some other bean.
if (!isAlias(beanName)) {
try {
// 通过名称来获取得到所有的bean的定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
// allowEagerInit通常来说都是true,所以后面的不需要来看了
// 尽管代码看得懂,但是不一定明白这里书写的意图
if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
boolean isFactoryBean = isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
boolean matchFound = false;
boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
// 判断是否是FactoryBean还是普通的bean
if (!isFactoryBean) {
if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
else {
if (includeNonSingletons || isNonLazyDecorated ||
(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
if (!matchFound) {
// 从这里看,这里考虑到了传递进来的参数中是加了&符号的,那么也就意味着for循环
// 中的beanName是没有包含factory中的beanName的
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably a placeholder: let's ignore it for type matching purposes.
LogMessage message = (ex instanceof CannotLoadBeanClassException ?
LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));
logger.trace(message, ex);
// Register exception, in case the bean was accidentally unresolvable.
onSuppressedException(ex);
}
catch (NoSuchBeanDefinitionException ex) {
// Bean definition got removed while we were iterating -> ignore.
}
}
}
都调用了isTypeMatch方法,那么来看一下对应的方法:
protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);
boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);
// Check manually registered singletons.
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
if (beanInstance instanceof FactoryBean) {
// 是否添加了&符号进来的
if (!isFactoryDereference) {
// factoryBean中的有一个需要重写的方法getObjectForType方法
// 这里考虑的是factorybean中如果说不是对应类型的bean,那么没有必要调用getObject方法进行实例化
// 而是直接通过getObjectType来进行判断是否是对应的类型
Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
return (type != null && typeToMatch.isAssignableFrom(type));
}
else {
return typeToMatch.isInstance(beanInstance);
}
}
// 不是facotybean并且方法名称不是加了&符号的
else if (!isFactoryDereference) {
if (typeToMatch.isInstance(beanInstance)) {
// Direct match for exposed instance?
return true;
}
else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
// Generics potentially only match on the target class, not on the proxy...
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
Class<?> targetType = mbd.getTargetType();
if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
// Check raw class match as well, making sure it's exposed on the proxy.
Class<?> classToMatch = typeToMatch.resolve();
if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
return false;
}
if (typeToMatch.isAssignableFrom(targetType)) {
return true;
}
}
ResolvableType resolvableType = mbd.targetType;
if (resolvableType == null) {
resolvableType = mbd.factoryMethodReturnType;
}
return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));
}
}
return false;
}
// NULLBEAN的情况,返回的是NULL,不需要再来进行判断
else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
// null instance registered
return false;
}
// 父工厂中也没有
// No singleton instance found -> check bean definition.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// No bean definition found in this factory -> delegate to parent.
return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch);
}
// 只能通过bean定义来判断是不是对应的类型的
// Retrieve corresponding bean definition.
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
// Setup the types that we want to match against
Class<?> classToMatch = typeToMatch.resolve();
if (classToMatch == null) {
classToMatch = FactoryBean.class;
}
Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch});
// Attempt to predict the bean type
Class<?> predictedType = null;
// We're looking for a regular reference but we're a factory bean that has
// a decorated bean definition. The target bean should be the same type
// as FactoryBean would ultimately return.
if (!isFactoryDereference && dbd != null && isFactoryBean(beanName, mbd)) {
// We should only attempt if the user explicitly set lazy-init to true
// and we know the merged bean definition is for a factory bean.
if (!mbd.isLazyInit() || allowFactoryBeanInit) {
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
Class<?> targetType = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
if (targetType != null && !FactoryBean.class.isAssignableFrom(targetType)) {
predictedType = targetType;
}
}
}
// If we couldn't use the target type, try regular prediction.
if (predictedType == null) {
predictedType = predictBeanType(beanName, mbd, typesToMatch);
if (predictedType == null) {
return false;
}
}
// Attempt to get the actual ResolvableType for the bean.
ResolvableType beanType = null;
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
if (FactoryBean.class.isAssignableFrom(predictedType)) {
if (beanInstance == null && !isFactoryDereference) {
beanType = getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit);
predictedType = beanType.resolve();
if (predictedType == null) {
return false;
}
}
}
else if (isFactoryDereference) {
// Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
// type but we nevertheless are being asked to dereference a FactoryBean...
// Let's check the original bean class and proceed with it if it is a FactoryBean.
predictedType = predictBeanType(beanName, mbd, FactoryBean.class);
if (predictedType == null || !FactoryBean.class.isAssignableFrom(predictedType)) {
return false;
}
}
// We don't have an exact type but if bean definition target type or the factory
// method return type matches the predicted type then we can use that.
if (beanType == null) {
ResolvableType definedType = mbd.targetType;
if (definedType == null) {
definedType = mbd.factoryMethodReturnType;
}
if (definedType != null && definedType.resolve() == predictedType) {
beanType = definedType;
}
}
// If we have a bean type use it so that generics are considered
if (beanType != null) {
return typeToMatch.isAssignableFrom(beanType);
}
// If we don't have a bean type, fallback to the predicted type
return typeToMatch.isAssignableFrom(predictedType);
}
那么再次回到根据类型找到bean的阶段:
// 来到这里的for循环。在spring容器启动的时候就可以向resolvableDependencies来添加对应的类型的bean
// 尝试从这里面来进行获取,这里在容器尚未启动阶段可以添加
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
// 生成对应的名称,因为添加的时候只是添加了对应类型的bean对象而已,没有指定名称
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
紧接着看下面的判断:
for (String candidate : candidateNames) {
// 不是自己的情况,则判断自己到底能不能来进行使用;如果有其他的bean,那么使用其他的;如果没有,直接自己的
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
// 先把其他的添加到result中来
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
result为空,有两种情况:1、要么是真的没有匹配到;2、要么是自己;
这里来看下对应的例子:
@Component
public class UserService implements BeanNameAware {
@Autowired
private UserService userService;
private String userName;
public void test(){
System.out.println(userService);
}
@Override
public void setBeanName(String name) {
this.userName = name;
}
@Override
public String toString() {
return "UserService{" +
"userName='" + userName + '\'' +
'}';
}
}
接着判断结果集是否为空:
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
// 判断类型是不是数组、集合之类的
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
// 在这里来判断是不是自己
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
多次看到了这个方法判断,下面符合的场景是这种使用方式:
@ComponentScan(basePackages = "com.guang.spring.demo8")
public class Demo8Config {
@Bean(autowireCandidate = true)
public OrderService orderService2(){
return new OrderService();
}
// 不能够进行依赖注入方式,所以容器中就一个,按照类型来进行注入
@Bean(autowireCandidate = false)
public OrderService orderService1(){
return new OrderService();
}
}
@Component
public class OrderController {
@Autowired
private OrderService orderService;
public void test(){
System.out.println(orderService);
}
}
这是另外一种使用方式来判断是否能够进行依赖注入的条件。
注入判断这里的是否能够进行依赖注入的条件:
1、QualifierAnnotationAutowireCandidateResolver.isAutowireCandidate
2、GenericTypeAwareAutowireCandidateResolver.isAutowireCandidate
3、SimpleAutowireCandidateResolver.isAutowireCandidate
如果父类判断出来了不能够进行依赖注入,直接返回FALSE;这里类似责任链模式;