关联博文
Spring后置处理器中的InstantiationAwareBeanPostProcessor详解
Spring中Bean实例化过程中的initializeBean方法
Spring中Bean实例化过程中的populateBean方法
Spring中@Autowired与@Resource自动注入实现原理
Spring中如何获取到一个Bean实例?
从autowiring使用上可以知道,这个autowiring属性在对Bean属性进行依赖注入时起作用。而这是在populateBean中实现的。也就是说,对属性autowiring的处理是populateBean的一部分。在前面我们分析Spring中Bean实例化过程中的populateBean方法可以看到自动注入的解析出现在两个部分。
第一部分:
// AbstractAutowireCapableBeanFactory#populateBean
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
第二部分:
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
在第一部分为解析自动注入标识resolvedAutowireMode,默认值为AutowireCapableBeanFactory.AUTOWIRE_NO
也就是0。当其为0时,不会执行autowireByName或者autowireByType逻辑。
postProcessProperties
则可以理解为一种补偿机制,比如AutowiredAnnotationBeanPostProcessor
的该方法,会尝试解析@Autowired
注解触发依赖Bean的获取过程。
接下来我们从源码角度分析这两部分的流程。
【1】autowireByName和autowireByType
① autowireByName
当resolvedAutowireMode为1时,即AUTOWIRE_BY_NAME
将会触发autowireByName(beanName, mbd, bw, newPvs);
。
方法源码如下:
//AbstractAutowireCapableBeanFactory#autowireByName
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取未满足的非简单类型的属性名称
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// 如果当前容器包含该属性名称对应的bean
if (containsBean(propertyName)) {
// 触发Bean的获取
Object bean = getBean(propertyName);
//更新pvs
pvs.add(propertyName, bean);
// 注册记录beanName与依赖 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");
}
}
}
}
方法如上所示,获取需要解析的依赖bean。遍历循环尝试从容器中获取bean,然后更新到pvs中。最后调用registerDependentBean方法进行beanName与依赖bean名称留存记录。
② registerDependentBean
registerDependentBean
方法如下所示,其使用dependentBeanMap
与dependenciesForBeanMap
记录了beanName都被依赖了哪些bean和dependentBeanName都依赖了哪些bean。
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
在DefaultSingletonBeanRegistry中维护了一系列final map。其中dependentBeanMap 表示 beanName---哪些bean依赖了beanName
,dependenciesForBeanMap 表示 beanName---beanName依赖了哪些bean
。
/** Map between dependent bean names: bean name to Set of dependent bean names. */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
③ autowireByType
// AbstractAutowireCapableBeanFactory#autowireByType
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);
// 获取未满足的非简单类型的bean名称/属性名称,
//如创建我们的XXXMapper时会解析sqlSessionFactory、sqlSessionTemplate
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.
// 如果属性类型是Object,直接抛出异常
if (Object.class != pd.getPropertyType()) {
// 获取写方法参数对象,就是setXXXXX方法的参数对象
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// 判断是否为PriorityOrdered对象,即可以忽略order排序规则
// 如果是PriorityOrdered则eager为false,否则为true。
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 核心方法,解析依赖
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
// 如果解析到依赖对象,比如sqlSessionFactory,那么放到pvs中
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//该方法前面提到过,注册记录bean与依赖bean的关系
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);
}
}
}
PropertyDescriptor 属性描述符。其包括属性名称、读方法、写方法、属性类型等。
MethodParameter,方法参数类型。其包括方法调用类、所属类、参数类型、参数个数、方法名称、方法返回类型、参数注解、异常类型等等。
如上代码所示,这里会解析得到propertyNames然后遍历解析依赖,之后会同autowireByName一样调用registerDependentBean方法注册记录bean与依赖bean的关系。
那么如何解析依赖呢?我们继续往下看。
④ 依赖解析resolveDependency
继续分析autowireByType,这部分我们分析依赖如何解析的。如下是DefaultListableBeanFactory
的resolveDependency
方法,这也是依赖解析的核心方法。在下文AutowiredAnnotationBeanPostProcessor
的inject同样流转到了该方法。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 默认是DefaultParameterNameDiscoverer,在分析springmvc流程中我们也提到过
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 判断依赖类型,通常这里是parameterType
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 {
// 这里是核心入口,这里是ContextAnnotationAutowireCandidateResolver
// 判断是否为Lazy,如果是则使用ProxyFactory创建代理
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 如果非Lazy,则进入实际依赖解析过程
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
如上代码所示,首先设置ParameterNameDiscoverer
,默认是DefaultParameterNameDiscoverer
。然后判断依赖类型,根据依赖类型进行不同的处理。其中在最后一部分中会判断是否为Lazy,如果是Lazy则使用ProxyFactory创建代理返回。如果不是Lazy则进入实际依赖解析过程。
Lazy时,创建代理的过程可以参考方法ContextAnnotationAutowireCandidateResolver的buildLazyResolutionProxy方法。
关于AutowireCandidateResolver
如下所示,DefaultListableBeanFactory内部维护了该成员默认是SimpleAutowireCandidateResolver。
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
但是在AnnotationConfigUtils
的registerAnnotationConfigProcessors
方法中会为容器设置解析器为ContextAnnotationAutowireCandidateResolver
,这整个候选解析器是QualifierAnnotationAutowireCandidateResolver
的子类。
我们继续看public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException
方法,这是实际解析依赖的入口。
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;
}
//获取依赖类型,比如interface org.apache.ibatis.session.SqlSessionFactory
Class<?> type = descriptor.getDependencyType();
// 这部分处理 @Value 注解
// value如${com.jane.file.baseFilePath}
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
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()));
}
}
// 处理集合类型,比如Array Map Collection
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 得到候选的、匹配的bean class实例:beanName---bean class 对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 如果为空且required,则抛出异常NoSuchBeanDefinitionException
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 如果有多个,则根据@Primary和@Priority进行抉择
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
//如果抉择不出,则可能抛出异常NoUniqueBeanDefinitionException
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();
// 解析得到的依赖bean名称
autowiredBeanName = entry.getKey();
// 解析得到的依赖bean实例-Class对象哦,还需要进一步解析
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
// 放入autowiredBeanNames,如sqlSessionFactory
autowiredBeanNames.add(autowiredBeanName);
}
// 如果实例是Class对象,则解析为真实的Bean实例对象
if (instanceCandidate instanceof Class) {
// beanFactory.getBean(beanName); 也就是getBean的过程
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
// 抛出NoSuchBeanDefinitionException
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
// 抛出BeanNotOfRequiredTypeException
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
如上代码所示,这里可以总结为三个核心方法:
resolveMultipleBeans
,处理集合类型,如Array、Map、Collection;findAutowireCandidates
,处理单个对象descriptor.resolveCandidate(autowiredBeanName, type, this);
,将Class对象解析为真实的bean实例,这里会触发getBean的过程。可以说真正的依赖解析是在这里实行的。
⑤ @Value
在上面方法中可以看到如下代码,其实就是对@Value注解做了处理。
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
如下所示,AbstractBeanFactory
的resolveEmbeddedValue
方法会尝试使用StringValueResolver
解析得到实际的Value值,比如本文这里的D://myfilemapping/bookrecommend/file
。
【2】postProcessProperties
这里指的是InstantiationAwareBeanPostProcessor
的postProcessProperties
。前面我们提到过,如果resolvedAutowireMode为0,那么是不会执行autowireByName或者autowireByType的逻辑的。此时@Autowired、@Resource注解就由postProcessProperties方法提供实习。
AutowiredAnnotationBeanPostProcessor处理@Autowired,CommonAnnotationBeanPostProcessor处理@Resource。
如下所示是AutowiredAnnotationBeanPostProcessor
的postProcessProperties方法,该方法首先获取到需要依赖注入的元素,然后调用注入方法得到实例对象。
@Override
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;
}
① 获取依赖注入的元素
如下所示AutowiredAnnotationBeanPostProcessor
的findAutowiringMetadata
方法找到那些标注了@Autowired注解的字段和方法,提取出来需要进行依赖解析的元素。
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
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) {
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));
}
});
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))) {
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));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
② 依赖注入对象解析
接下来我们再看一下注入过程
// 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) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
// AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
// 这是缓存机制
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
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) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
// 记录bean与依赖bean的关系
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
// 如果value不为null,则为filed赋值value
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
如上代码所示,这里核心逻辑就是 beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
其将会触发依赖解析过程也就是【1】中的第③部分。
③ @Resource
当你controller有@Resource注解时,CommonAnnotationBeanPostProcessor的postProcessProperties方法就会去解析并注入。
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 首先从缓存里面查找
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// metadata == null || metadata.targetClass != clazz
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
// 加锁--双重校验锁
synchronized (this.injectionMetadataCache) {
//再次从缓存获取
metadata = this.injectionMetadataCache.get(cacheKey);
// 再次进行判断
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 核心在这里,根据Bean类型获取其需要处理的@Resource元素
metadata = buildResourceMetadata(clazz);
// 放入缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
我们看下其收集元素的方法,这里将会收集目标元素如WebServiceRefElement(@WebServiceRef)
、EjbRefElement(@EJB)
及我们常用的ResourceElement(@Resource)
。
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 从field字段级别收集
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
// 从方法级别收集
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
获取到目标元素后(比如我们@Resource注解的对象),其将会通过如下方法调用栈进行依赖的解析。
// 方法调用栈
InjectionMetadata#inject ->
InjectionMetadata.InjectedElement#inject ->
CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject ->
CommonAnnotationBeanPostProcessor#getResource ->
CommonAnnotationBeanPostProcessor#autowireResource ->
DefaultListableBeanFactory#resolveDependency
这里我们最后可以看到,其同样走到了DefaultListableBeanFactoryd
的resolveDependency
方法,不再赘述。
需要注意一点的是,同@Autowired解析依赖的过程一样,这里也实现了lazyLookup 兼容。如果lazyLookup 为true,则创建代理,不触发实际对象解析。
// CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}