Spring源码之@Lookup注解解析

        众所周知,Spring中的Bean默认都是单例的,如果想要每次返回的不一样,类上加@Scope注解,并指定scope属性为PROTOTYPE类型的时候,在每次注入的时候会自动创建一个新的bean实例。看一下这个例子:

/**
 * @ClassName: LookupService 
 * @Description: 测试原型Bean的注入
 * @Author: Kaisheng Du
 * @Date: 2021/10/25 14:34
 * @Version: 1.0
 */
@Component
@Scope("prototype")
public class LookupService {
    
}
@Component
public class GoodsService {

    @Autowired
    private LookupService lookupService;

    public LookupService test(){
        return lookupService;
    }
}

测试代码:

    @Test
    public void testLookup() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
        GoodsService goodsService = applicationContext.getBean(GoodsService.class);
        for (int i = 0; i < 3; i++) {
            System.out.println(goodsService.test());
        }
    }

打印结果:

cn.kieasar.service.LookupService@51dcb805
cn.kieasar.service.LookupService@51dcb805
cn.kieasar.service.LookupService@51dcb805

        调用3次test()方法,返回的结果却是同样的,你不是说LookupService是多例吗?

        是不是很奇怪,因为GoodsService 是单例的,它创建的时候赋值给LookupService属性的就是刚开始的那个Bean,后面执行test()方法的时候,调用的都是同一个LookupService的Bean对象,所以它的hashCode相同。

        那如何每次拿到的都不一样呢?使用@Lookup注解:

@Component
public class GoodsService {

    @Autowired
    private LookupService lookupService;

    @Lookup("lookupService")
    public LookupService test(){
        return null;
    }

}

        我们再看打印结果:

cn.kieasar.service.LookupService@306f16f3
cn.kieasar.service.LookupService@702b8b12
cn.kieasar.service.LookupService@22e357dc

        这次就是我们要的效果了~

        接下来我们看一下@Lookup注解的实现原理:

        在Bean的实例化过程中,在推断构造方法determineCandidateConstructors()逻辑中除了去选择构造方法以及查找入参对象之外,会还判断是否在对应的类中是否存在使用@Lookup注解的方法。如果存在则把该方法封装为LookupOverride对象并添加到BeanDefinition中。 
        在实例化时,如果判断出来当前BeanDefinition中没有LookupOverride,就直接用构造方法反射得到一个实例对象。如果存在LookupOverride对象,也就是类中存在@Lookup注解了的方法,那就会生成一个代理对象。@Lookup注解就是方法注入。

所属类:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

	// 完成有@Autowied注解的有参构造函数的实例化
	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {

		// Let's check for lookup methods here...
		if (!this.lookupMethodsChecked.contains(beanName)) {
			// 对@Lookup注解的支撑
			if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
				try {
					Class<?> targetClass = beanClass;
					do {
						ReflectionUtils.doWithLocalMethods(targetClass, method -> {
							Lookup lookup = method.getAnnotation(Lookup.class);
							if (lookup != null) {
								Assert.state(this.beanFactory != null, "No BeanFactory available");
                                	// 将当前method封装成LookupOverride,并设置到BeanDefinition的methodOverrides属性中
								LookupOverride override = new LookupOverride(method, lookup.value());
								try {
									RootBeanDefinition mbd = (RootBeanDefinition)
											this.beanFactory.getMergedBeanDefinition(beanName);
									mbd.getMethodOverrides().addOverride(override);
								}
								catch (NoSuchBeanDefinitionException ex) {
									throw new BeanCreationException(beanName,
											"Cannot apply @Lookup to beans without corresponding bean definition");
								}
							}
						});
						targetClass = targetClass.getSuperclass();
					}
					while (targetClass != null && targetClass != Object.class);

				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
				}
			}
			this.lookupMethodsChecked.add(beanName);
		}

		// Quick check on the concurrent map first, with minimal locking.
		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			synchronized (this.candidateConstructorsCache) {
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
						rawCandidates = beanClass.getDeclaredConstructors();
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					// candidates用来装构造函数
					List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
					// 用来记录required为true的构造方法,一个类中只能有一个为true的构造方法
					Constructor<?> requiredConstructor = null;
					// 用来记录默认的无参构造方法
					Constructor<?> defaultConstructor = null;
					// kotlin相关,不用管
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
					// 遍历每个构造方法
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							// 记录一下普通的构造方法
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
						// 找@Autowired注解的过程,进入findAutowiredAnnotation()****
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
							// 如果beanClass是代理类,获取到被代理类的类型
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						// 不为空,表示当前构造方法上加了@Autowired注解
						if (ann != null) {
							// 一个类中只能有一个required为true的构造方法,不能还有其他@Autowired的构造方法,否则会报错
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							// 拿到 @Autowired 注解的 required 属性值,如果是 true
							boolean required = determineRequiredStatus(ann);
							if (required) {
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								// 记录required属性为true的构造方法
								requiredConstructor = candidate;
							}
							// 只要加了@Autowired注解,不管有无参数,requred属性为true和false,都加入到集合中
							candidates.add(candidate);
						}
						// 表示无参构造方法
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							else if (candidates.size() == 1 && logger.isInfoEnabled()) {
								logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						// 如果只有一个required为true的构造方法,那就只有中一个是合格的
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					// 没有添加Autowired注解的构造方法,且只有一个、且是有参的
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					else {
                        // 如果有多个有参、且没有@Autowired注解的构造方法,则返回空
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}

        这里会对@Lookup注解的支持,如果当前创建Bean的某个方法上有@Lookup注解,将当前method封装成LookupOverride,并设置到BeanDefinition的methodOverrides属性中,

        然后在后面无参构造函数的实例化方法SimpleInstantiationStrategy.instantiate()会判断判断当前BeanDefinition对应的beanClass中是否存在@Lookup注解的方法,存在的话生成代理对象:

        所属类:org.springframework.beans.factory.support.SimpleInstantiationStrategy

	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		// 判断当前BeanDefinition对应的beanClass中是否存在@Lookup注解的方法
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			// constructorToUse就是缓存的无参构造方法
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			// 如果有@Lookup注解,则生成一个代理对象
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

        调用到SimpleInstantiationStrategy子类CglibSubclassingInstantiationStrategy的instantiateWithMethodInjection()方法:

	@Override
	protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		return instantiateWithMethodInjection(bd, beanName, owner, null);
	}

	@Override
	protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Constructor<?> ctor, Object... args) {

		// Must generate CGLIB subclass...
		return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
	}

        看实例化方法instantiate():

        所属类:org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy

.CglibSubclassCreator 

public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
			Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
			Object instance;
			if (ctor == null) {
				instance = BeanUtils.instantiateClass(subclass);
			}
			else {
				try {
					Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
					instance = enhancedSubclassConstructor.newInstance(args);
				}
				catch (Exception ex) {
					throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
							"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
				}
			}
			// SPR-10785: set callbacks directly on the instance instead of in the
			// enhanced class (via the Enhancer) in order to avoid memory leaks.
            // 主要看LookupOverrideMethodInterceptor类,该类实现了MethodInterceptor接口,生成代理的逻辑在intercept()方法
            // ReplaceOverrideMethodInterceptor类是对XML中replaced-method标签的支持,作用是替换方法,但是需要新建一个类实现MethodReplacer接口
			Factory factory = (Factory) instance;
			factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
					new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
					new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
			return instance;
		}

        这里有个LookupOverrideMethodInterceptor类,它是CglibSubclassingInstantiationStrategy的内部类,专门处理@Lookup注解的实例化,该类实现了MethodInterceptor接口,生成代理的逻辑在intercept()方法:

        所属类:org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy

.LookupOverrideMethodInterceptor

private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

		private final BeanFactory owner;

		public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
			super(beanDefinition);
			this.owner = owner;
		}

		@Override
		public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
			// Cast is safe, as CallbackFilter filters are used selectively.
			LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
			Assert.state(lo != null, "LookupOverride not found");
			Object[] argsToUse = (args.length > 0 ? args : null);  // if no-arg, don't insist on args at all
			if (StringUtils.hasText(lo.getBeanName())) {
				// 根据@Lookup注解配置的beanName去BeanFactory中获取Bean对象,(没有执行有@Lookup注解的方法)
				return (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
						this.owner.getBean(lo.getBeanName()));
			}
			else {
				return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) :
						this.owner.getBean(method.getReturnType()));
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/qq_40213907/article/details/120951107