io.seata.spring.tcc.TccAnnotationProcessor Maven / Gradle / Ivy
/*
* Copyright 1999-2019 Seata.io Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.seata.spring.tcc;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
import io.seata.rm.tcc.remoting.RemotingDesc;
import io.seata.spring.util.TCCBeanParserUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* An annotation adapter for TCC
*
* @author ppf
*/
public class TccAnnotationProcessor implements BeanPostProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(TccAnnotationProcessor.class);
private static final List> ANNOTATIONS = new ArrayList<>(4);
private static final Set PROXIED_SET = new HashSet<>();
static {
ANNOTATIONS.add(loadAnnotation("org.apache.dubbo.config.annotation.Reference"));
ANNOTATIONS.add(loadAnnotation("com.alipay.sofa.runtime.api.annotation.SofaReference"));
}
private static Class extends Annotation> loadAnnotation(String annotation) {
try {
return (Class extends Annotation>) Class.forName(annotation);
} catch (ClassNotFoundException e) {
return null;
}
}
/**
* Process annotation
*
* @param bean the bean
* @param beanName the bean name
* @param annotation the annotation
*/
protected void process(Object bean, String beanName, Class extends Annotation> annotation) {
if (Objects.isNull(annotation) || PROXIED_SET.contains(beanName)) {
return;
}
ReflectionUtils.doWithFields(bean.getClass(), field -> {
Annotation reference = field.getAnnotation(annotation);
if (reference == null) {
return;
}
addTccAdvise(bean, beanName, field, field.getType());
}, field -> !Modifier.isStatic(field.getModifiers())
&& (field.isAnnotationPresent(annotation)));
PROXIED_SET.add(beanName);
}
/**
* Add TCC interceptor for tcc proxy bean
*
* @param bean the bean
* @param beanName the bean name
* @param field the field
* @param serviceClass the serviceClass
* @throws IllegalAccessException the illegal access exception
*/
public void addTccAdvise(Object bean, String beanName, Field field, Class serviceClass) throws IllegalAccessException {
Object fieldValue = field.get(bean);
if (fieldValue == null) {
return;
}
for (Method method : field.getType().getMethods()) {
if (!Modifier.isStatic(method.getModifiers()) && (method.isAnnotationPresent(TwoPhaseBusinessAction.class))) {
RemotingDesc remotingDesc = new RemotingDesc();
remotingDesc.setServiceClass(serviceClass);
TccActionInterceptor actionInterceptor = new TccActionInterceptor(remotingDesc);
Object proxyBean = TCCBeanParserUtils.createProxy(serviceClass, fieldValue, actionInterceptor);
field.setAccessible(true);
field.set(bean, proxyBean);
LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy [" + actionInterceptor.getClass().getName() + "]");
}
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
for (Class extends Annotation> annotation : ANNOTATIONS) {
process(bean, beanName, annotation);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy