use of com.alipay.sofa.runtime.api.annotation.SofaService in project sofa-boot by alipay.
the class ServiceBeanFactoryPostProcessor method generateSofaServiceDefinition.
@SuppressWarnings("unchecked")
private void generateSofaServiceDefinition(String beanId, SofaService sofaServiceAnnotation, Class<?> beanClass, BeanDefinition beanDefinition, ConfigurableListableBeanFactory beanFactory) {
if (sofaServiceAnnotation == null) {
return;
}
AnnotationWrapperBuilder<SofaService> wrapperBuilder = AnnotationWrapperBuilder.wrap(sofaServiceAnnotation).withBinder(binder);
sofaServiceAnnotation = wrapperBuilder.build();
Class<?> interfaceType = sofaServiceAnnotation.interfaceType();
if (interfaceType.equals(void.class)) {
Class<?>[] interfaces = beanClass.getInterfaces();
if (beanClass.isInterface() || interfaces == null || interfaces.length == 0) {
interfaceType = beanClass;
} else if (interfaces.length == 1) {
interfaceType = interfaces[0];
} else {
throw new FatalBeanException(ErrorCode.convert("01-02004", beanId));
}
}
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
String serviceId = SofaBeanNameGenerator.generateSofaServiceBeanName(interfaceType, sofaServiceAnnotation.uniqueId());
if (!beanFactory.containsBeanDefinition(serviceId)) {
builder.getRawBeanDefinition().setScope(beanDefinition.getScope());
builder.setLazyInit(beanDefinition.isLazyInit());
builder.getRawBeanDefinition().setBeanClass(ServiceFactoryBean.class);
builder.addAutowiredProperty(AbstractContractDefinitionParser.SOFA_RUNTIME_CONTEXT);
builder.addAutowiredProperty(AbstractContractDefinitionParser.BINDING_CONVERTER_FACTORY);
builder.addAutowiredProperty(AbstractContractDefinitionParser.BINDING_ADAPTER_FACTORY);
builder.addPropertyValue(AbstractContractDefinitionParser.INTERFACE_CLASS_PROPERTY, interfaceType);
builder.addPropertyValue(AbstractContractDefinitionParser.UNIQUE_ID_PROPERTY, sofaServiceAnnotation.uniqueId());
builder.addPropertyValue(AbstractContractDefinitionParser.BINDINGS, getSofaServiceBinding(sofaServiceAnnotation, sofaServiceAnnotation.bindings()));
builder.addPropertyReference(ServiceDefinitionParser.REF, beanId);
builder.addPropertyValue(ServiceDefinitionParser.BEAN_ID, beanId);
builder.addPropertyValue(AbstractContractDefinitionParser.DEFINITION_BUILDING_API_TYPE, true);
builder.addDependsOn(beanId);
((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(serviceId, builder.getBeanDefinition());
} else {
SofaLogger.warn("SofaService was already registered: {}", serviceId);
}
}
use of com.alipay.sofa.runtime.api.annotation.SofaService 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.SofaService in project sofa-boot by alipay.
the class ServiceBeanFactoryPostProcessor method generateSofaServiceDefinitionOnClass.
private void generateSofaServiceDefinitionOnClass(String beanId, Class<?> beanClass, BeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
// See issue: https://github.com/sofastack/sofa-boot/issues/835
SofaService sofaServiceAnnotation = AnnotationUtils.findAnnotation(beanClass, SofaService.class);
generateSofaServiceDefinition(beanId, sofaServiceAnnotation, beanClass, beanDefinition, registry);
}
use of com.alipay.sofa.runtime.api.annotation.SofaService in project sofa-boot by alipay.
the class AnnotationPlaceHolderTest method testServiceAnnotationPlaceHolder.
@Test
@SuppressWarnings("unchecked")
public void testServiceAnnotationPlaceHolder() {
PlaceHolderBinder binder = new PlaceHolderBinder() {
@Override
public String bind(String origin) {
return environment.resolvePlaceholders(origin);
}
};
SofaService sofaService = AnnotationSampleService.class.getAnnotation(SofaService.class);
PlaceHolderAnnotationInvocationHandler.AnnotationWrapperBuilder<SofaService> builder = PlaceHolderAnnotationInvocationHandler.AnnotationWrapperBuilder.wrap(sofaService).withBinder(binder);
SofaService delegate = builder.build();
Assert.assertEquals(sofaService.hashCode(), delegate.hashCode());
Assert.assertEquals(sofaService.toString(), delegate.toString());
Assert.assertEquals(SampleService.class, sofaService.interfaceType());
Assert.assertEquals(SampleService.class, delegate.interfaceType());
Assert.assertEquals("${annotation.sample.service.uniqueId}", sofaService.uniqueId());
Assert.assertEquals("annotation-sample-service-uniqueId", delegate.uniqueId());
Assert.assertEquals(1, sofaService.bindings().length);
Assert.assertEquals(1, delegate.bindings().length);
SofaServiceBinding binding = sofaService.bindings()[0];
String[] filters = binding.filters();
SofaServiceBinding delegateBinding = delegate.bindings()[0];
String[] delegateFilters = delegateBinding.filters();
Assert.assertEquals("${annotation.sample.service.bindingType}", binding.bindingType());
Assert.assertEquals("bolt", delegateBinding.bindingType());
Assert.assertEquals(300, binding.timeout());
Assert.assertEquals(300, delegateBinding.timeout());
Assert.assertEquals(2, filters.length);
Assert.assertEquals(2, delegateFilters.length);
Assert.assertEquals("${annotation.sample.service.filter-1}", filters[0]);
Assert.assertEquals("service-filter-1", delegateFilters[0]);
Assert.assertEquals("filter-2", filters[1]);
Assert.assertEquals("filter-2", delegateFilters[1]);
Assert.assertTrue(delegate instanceof WrapperAnnotation);
Assert.assertTrue(delegateBinding instanceof WrapperAnnotation);
}
use of com.alipay.sofa.runtime.api.annotation.SofaService in project sofa-boot by alipay.
the class ServiceAnnotationBeanPostProcessor method processSofaService.
private void processSofaService(Object bean, String beanName) {
final Class<?> beanClass = AopProxyUtils.ultimateTargetClass(bean);
SofaService sofaServiceAnnotation = beanClass.getAnnotation(SofaService.class);
if (sofaServiceAnnotation == null) {
return;
}
Class<?> interfaceType = sofaServiceAnnotation.interfaceType();
if (interfaceType.equals(void.class)) {
Class<?>[] interfaces = beanClass.getInterfaces();
if (interfaces == null || interfaces.length == 0 || interfaces.length > 1) {
throw new ServiceRuntimeException("Bean " + beanName + " does not has any interface or has more than one interface.");
}
interfaceType = interfaces[0];
}
Implementation implementation = new SpringImplementationImpl(beanName, applicationContext);
implementation.setTarget(bean);
Service service = new ServiceImpl(sofaServiceAnnotation.uniqueId(), interfaceType, InterfaceMode.annotation, bean);
service.addBinding(new JvmBinding());
ComponentInfo componentInfo = new ServiceComponent(implementation, service, sofaRuntimeContext);
sofaRuntimeContext.getComponentManager().register(componentInfo);
}
Aggregations