CASE
image.png基类
import com.alibaba.dubbo.config.annotation.Reference;
import com.abci.IAbtDispacherService;
public abstract class AbstractService {
@Reference(version = "1.0", registry = "provider", timeout = 50, retries = -1, lazy = true)
public IAbtDispacherService iAbtDispacherService;//这里为空
public void test() {
System.out.println(iAbtDispacherService);
}
}
子类
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {MSApplication.class},
initializers = {ConfigFileApplicationContextInitializer.class})
public class HomePageTest extends AbstractService{
@Reference(version = "1.0", registry = "provider", timeout = 50, retries = -1, lazy = true)
public IAbtDispacherService iAbtDispacherService22;
@Test
public void missFreshHomepage() {
this.test();
}
}
原因(Field field : objClz.getDeclaredFields)
package com.alibaba.dubbo.spring.boot;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import com.alibaba.dubbo.spring.boot.bean.ClassIdBean;
/**
* DubboConsumerAutoConfiguration
*
* @author xionghui
* @version 2.0.0
* @since 1.0.0
*/
@Configuration
@ConditionalOnClass(Service.class)
@ConditionalOnBean(annotation = EnableDubboConfiguration.class)
@AutoConfigureAfter(DubboAutoConfiguration.class)
@EnableConfigurationProperties(DubboProperties.class)
public class DubboConsumerAutoConfiguration extends DubboCommonAutoConfiguration {
private static final Map<ClassIdBean, Object> DUBBO_REFERENCES_MAP =
new ConcurrentHashMap<ClassIdBean, Object>();
@Autowired
private ApplicationContext applicationContext;
@Autowired
private DubboProperties properties;
public static Object getDubboReference(ClassIdBean classIdBean) {
return DUBBO_REFERENCES_MAP.get(classIdBean);
}
@Bean
public BeanPostProcessor beanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
Class<?> objClz;
if (AopUtils.isAopProxy(bean)) {
objClz = AopUtils.getTargetClass(bean);
} else {
objClz = bean.getClass();
}
try {
for (Field field : objClz.getDeclaredFields()) {//"这里有bug"
Reference reference = field.getAnnotation(Reference.class);
if (reference != null) {
DubboConsumerAutoConfiguration.this
.initIdConfigMap(DubboConsumerAutoConfiguration.this.properties);
ReferenceBean<?> referenceBean =
DubboConsumerAutoConfiguration.this.getConsumerBean(beanName, field, reference);
Class<?> interfaceClass = referenceBean.getInterfaceClass();
String group = referenceBean.getGroup();
String version = referenceBean.getVersion();
ClassIdBean classIdBean = new ClassIdBean(interfaceClass, group, version);
Object dubboReference =
DubboConsumerAutoConfiguration.DUBBO_REFERENCES_MAP.get(classIdBean);
if (dubboReference == null) {
synchronized (this) {
// double check
dubboReference =
DubboConsumerAutoConfiguration.DUBBO_REFERENCES_MAP.get(classIdBean);
if (dubboReference == null) {
referenceBean.afterPropertiesSet();
// dubboReference should not be null, otherwise it will cause
// NullPointerException
dubboReference = referenceBean.getObject();
DubboConsumerAutoConfiguration.DUBBO_REFERENCES_MAP.put(classIdBean,
dubboReference);
}
}
}
field.setAccessible(true);
field.set(bean, dubboReference);
}
}
} catch (Exception e) {
throw new BeanCreationException(beanName, e);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
};
}
/**
* init consumer bean
*
* @param interfaceClazz interfaceClazz
* @param reference reference
* @return ReferenceBean<T>
* @throws BeansException BeansException
*/
private <T> ReferenceBean<T> getConsumerBean(String beanName, Field field, Reference reference)
throws BeansException {
ReferenceBean<T> referenceBean = new ReferenceBean<T>(reference);
if ((reference.interfaceClass() == null || reference.interfaceClass() == void.class)
&& (reference.interfaceName() == null || "".equals(reference.interfaceName()))) {
referenceBean.setInterface(field.getType());
}
Environment environment = this.applicationContext.getEnvironment();
String application = reference.application();
referenceBean.setApplication(this.parseApplication(application, this.properties, environment,
beanName, field.getName(), "application", application));
String module = reference.module();
referenceBean.setModule(this.parseModule(module, this.properties, environment, beanName,
field.getName(), "module", module));
String[] registries = reference.registry();
referenceBean.setRegistries(this.parseRegistries(registries, this.properties, environment,
beanName, field.getName(), "registry"));
String monitor = reference.monitor();
referenceBean.setMonitor(this.parseMonitor(monitor, this.properties, environment, beanName,
field.getName(), "monitor", monitor));
String consumer = reference.consumer();
referenceBean.setConsumer(this.parseConsumer(consumer, this.properties, environment, beanName,
field.getName(), "consumer", consumer));
referenceBean.setApplicationContext(DubboConsumerAutoConfiguration.this.applicationContext);
return referenceBean;
}
@Override
protected String buildErrorMsg(String... errors) {
if (errors == null || errors.length != 4) {
return super.buildErrorMsg(errors);
}
return new StringBuilder().append("beanName=").append(errors[0]).append(", field=")
.append(errors[1]).append(", ").append(errors[2]).append("=").append(errors[3])
.append(" not found in multi configs").toString();
}
}
Returns an array of {@code Field} objects reflecting all the fields
declared by the class or interface represented by this
{@code Class} object. This includes public, protected, default
(package) access, and private fields, but excludes inherited fields.
/**
* Returns an array of {@code Field} objects reflecting all the fields
* declared by the class or interface represented by this
* {@code Class} object. This includes public, protected, default
* (package) access, and private fields, but excludes inherited fields.
*
* <p> If this {@code Class} object represents a class or interface with no
* declared fields, then this method returns an array of length 0.
*
* <p> If this {@code Class} object represents an array type, a primitive
* type, or void, then this method returns an array of length 0.
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
* @return the array of {@code Field} objects representing all the
* declared fields of this class
* @throws SecurityException
* If a security manager, <i>s</i>, is present and any of the
* following conditions is met:
*
* <ul>
*
* <li> the caller's class loader is not the same as the
* class loader of this class and invocation of
* {@link SecurityManager#checkPermission
* s.checkPermission} method with
* {@code RuntimePermission("accessDeclaredMembers")}
* denies access to the declared fields within this class
*
* <li> the caller's class loader is not the same as or an
* ancestor of the class loader for the current class and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the package
* of this class
*
* </ul>
*
* @since JDK1.1
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyFields(privateGetDeclaredFields(false));
}
网友评论