use of com.alipay.sofa.runtime.api.annotation.SofaReference in project sofa-boot by alipay.
the class ServiceBeanFactoryPostProcessor method generateSofaServiceDefinitionOnMethod.
private void generateSofaServiceDefinitionOnMethod(String beanId, AnnotatedBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
Class<?> returnType;
Class<?> declaringClass;
List<Method> candidateMethods = new ArrayList<>();
MethodMetadata methodMetadata = beanDefinition.getFactoryMethodMetadata();
try {
returnType = ClassUtils.forName(methodMetadata.getReturnTypeName(), null);
declaringClass = ClassUtils.forName(methodMetadata.getDeclaringClassName(), null);
} catch (Throwable throwable) {
// it's impossible to catch throwable here
SofaLogger.error(ErrorCode.convert("01-02001", beanId), throwable);
return;
}
if (methodMetadata instanceof StandardMethodMetadata) {
candidateMethods.add(((StandardMethodMetadata) methodMetadata).getIntrospectedMethod());
} else {
for (Method m : declaringClass.getDeclaredMethods()) {
// check methodName and return type
if (!m.getName().equals(methodMetadata.getMethodName()) || !m.getReturnType().getTypeName().equals(methodMetadata.getReturnTypeName())) {
continue;
}
// check bean method
if (!AnnotatedElementUtils.hasAnnotation(m, Bean.class)) {
continue;
}
Bean bean = m.getAnnotation(Bean.class);
Set<String> beanNames = new HashSet<>();
beanNames.add(m.getName());
if (bean != null) {
beanNames.addAll(Arrays.asList(bean.name()));
beanNames.addAll(Arrays.asList(bean.value()));
}
// check bean name
if (!beanNames.contains(beanId)) {
continue;
}
candidateMethods.add(m);
}
}
if (candidateMethods.size() == 1) {
SofaService sofaServiceAnnotation = candidateMethods.get(0).getAnnotation(SofaService.class);
if (sofaServiceAnnotation == null) {
sofaServiceAnnotation = returnType.getAnnotation(SofaService.class);
}
generateSofaServiceDefinition(beanId, sofaServiceAnnotation, returnType, beanDefinition, registry);
generateSofaReferenceDefinition(beanId, candidateMethods.get(0), registry);
} else if (candidateMethods.size() > 1) {
for (Method m : candidateMethods) {
if (AnnotatedElementUtils.hasAnnotation(m, SofaService.class) || AnnotatedElementUtils.hasAnnotation(returnType, SofaService.class)) {
throw new FatalBeanException(ErrorCode.convert("01-02002", declaringClass.getCanonicalName()));
}
if (Stream.of(m.getParameterAnnotations()).flatMap(Stream::of).anyMatch(annotation -> annotation instanceof SofaReference)) {
throw new FatalBeanException(ErrorCode.convert("01-02003", declaringClass.getCanonicalName()));
}
}
}
}
use of com.alipay.sofa.runtime.api.annotation.SofaReference in project sofa-boot by alipay.
the class ServiceBeanFactoryPostProcessor method doGenerateSofaReferenceDefinition.
@SuppressWarnings("unchecked")
private void doGenerateSofaReferenceDefinition(BeanDefinition beanDefinition, SofaReference sofaReference, Class<?> parameterType, BeanDefinitionRegistry registry) {
Assert.isTrue(JvmBinding.JVM_BINDING_TYPE.getType().equals(sofaReference.binding().bindingType()), "Only jvm type of @SofaReference on parameter is supported.");
AnnotationWrapperBuilder<SofaReference> wrapperBuilder = AnnotationWrapperBuilder.wrap(sofaReference).withBinder(binder);
sofaReference = wrapperBuilder.build();
Class<?> interfaceType = sofaReference.interfaceType();
if (interfaceType.equals(void.class)) {
interfaceType = parameterType;
}
String uniqueId = sofaReference.uniqueId();
String referenceId = SofaBeanNameGenerator.generateSofaReferenceBeanName(interfaceType, uniqueId);
// build sofa reference definition
if (!registry.containsBeanDefinition(referenceId)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
builder.getRawBeanDefinition().setScope(beanDefinition.getScope());
builder.getRawBeanDefinition().setLazyInit(beanDefinition.isLazyInit());
builder.getRawBeanDefinition().setBeanClass(ReferenceFactoryBean.class);
builder.addAutowiredProperty(AbstractContractDefinitionParser.SOFA_RUNTIME_CONTEXT);
builder.addAutowiredProperty(AbstractContractDefinitionParser.BINDING_CONVERTER_FACTORY);
builder.addAutowiredProperty(AbstractContractDefinitionParser.BINDING_ADAPTER_FACTORY);
builder.addPropertyValue(AbstractContractDefinitionParser.UNIQUE_ID_PROPERTY, uniqueId);
builder.addPropertyValue(AbstractContractDefinitionParser.INTERFACE_CLASS_PROPERTY, interfaceType);
builder.addPropertyValue(AbstractContractDefinitionParser.BINDINGS, getSofaReferenceBinding(sofaReference, sofaReference.binding()));
builder.addPropertyValue(AbstractContractDefinitionParser.DEFINITION_BUILDING_API_TYPE, true);
registry.registerBeanDefinition(referenceId, builder.getBeanDefinition());
}
// add bean dependency relationship
if (beanDefinition.getDependsOn() == null) {
beanDefinition.setDependsOn(referenceId);
} else {
String[] added = ObjectUtils.addObjectToArray(beanDefinition.getDependsOn(), referenceId);
beanDefinition.setDependsOn(added);
}
}
use of com.alipay.sofa.runtime.api.annotation.SofaReference in project sofa-boot by alipay.
the class ServiceBeanFactoryPostProcessor method generateSofaReferenceDefinition.
private void generateSofaReferenceDefinition(String beanId, Method method, BeanDefinitionRegistry registry) {
Class<?>[] parameterTypes = method.getParameterTypes();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; ++i) {
for (Annotation annotation : parameterAnnotations[i]) {
if (annotation instanceof SofaReference) {
doGenerateSofaReferenceDefinition(registry.getBeanDefinition(beanId), (SofaReference) annotation, parameterTypes[i], registry);
}
}
}
}
use of com.alipay.sofa.runtime.api.annotation.SofaReference in project sofa-boot by alipay.
the class SofaParameterNameDiscoverer method transformParameterNames.
@SuppressWarnings("unchecked")
protected String[] transformParameterNames(String[] parameterNames, Class<?>[] parameterType, Annotation[][] annotations) {
for (int i = 0; i < annotations.length; ++i) {
for (Annotation annotation : annotations[i]) {
if (annotation instanceof SofaReference) {
AnnotationWrapperBuilder<SofaReference> wrapperBuilder = AnnotationWrapperBuilder.wrap(annotation).withBinder(binder);
SofaReference delegate = wrapperBuilder.build();
Class interfaceType = delegate.interfaceType();
if (interfaceType.equals(void.class)) {
interfaceType = parameterType[i];
}
String uniqueId = delegate.uniqueId();
parameterNames[i] = SofaBeanNameGenerator.generateSofaReferenceBeanName(interfaceType, uniqueId);
}
}
}
return parameterNames;
}
use of com.alipay.sofa.runtime.api.annotation.SofaReference in project sofa-boot by alipay.
the class ServiceAnnotationBeanPostProcessor method processSofaReference.
private void processSofaReference(final Object bean) {
final Class<?> beanClass = bean.getClass();
ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
SofaReference sofaReferenceAnnotation = field.getAnnotation(SofaReference.class);
if (sofaReferenceAnnotation == null) {
return;
}
Class<?> interfaceType = sofaReferenceAnnotation.interfaceType();
if (interfaceType.equals(void.class)) {
interfaceType = field.getType();
}
Reference reference = new ReferenceImpl(sofaReferenceAnnotation.uniqueId(), interfaceType, InterfaceMode.annotation, false, false);
reference.addBinding(new JvmBinding());
Object proxy = ReferenceRegisterHelper.registerReference(reference, sofaRuntimeContext);
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, bean, proxy);
}
}, new ReflectionUtils.FieldFilter() {
@Override
public boolean matches(Field field) {
return !Modifier.isStatic(field.getModifiers()) && field.isAnnotationPresent(SofaReference.class);
}
});
}
Aggregations