用aop注解的方式实现 数据库mapper层每个方法的调用 改为微服务feign调用 并用反射解决多个feign方法的入参返参不同的问题 并给出详细示例
时间: 2024-06-08 10:11:47 浏览: 212
Java反射根据不同方法名动态调用不同的方法(实例)
好的,我明白了您的问题。首先,您可以使用AOP注解在数据库mapper层中进行切面编程,实现每个方法的调用改为微服务feign调用。您可以使用Spring Cloud Feign来实现微服务调用,并使用反射解决多个feign方法的入参和返参不同的问题。
以下是示例代码:
1. 定义注解
```java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FeignInterface {
String serviceName() default "";
String methodName() default "";
}
```
2. 实现切面
```java
@Aspect
@Component
public class FeignAspect {
@Autowired
private FeignClientFactory feignClientFactory;
@Around("@annotation(com.example.demo.annotations.FeignInterface)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
Class<?> returnType = method.getReturnType();
FeignInterface annotation = method.getAnnotation(FeignInterface.class);
String serviceName = annotation.serviceName();
String methodName = annotation.methodName();
Object[] args = joinPoint.getArgs();
FeignClient<?> feignClient = feignClientFactory.getFeignClient(serviceName);
if (feignClient == null) {
throw new RuntimeException(String.format("Cannot find feign client with service name: %s!", serviceName));
}
Object result = null;
if (StringUtils.isEmpty(methodName)) {
result = feignClient.invoke(args, returnType);
} else {
result = feignClient.invoke(methodName, args, returnType);
}
return result;
}
}
```
3. 实现Feign客户端
```java
public interface FeignClient<T> {
T invoke(Object[] args, Class<T> returnType) throws Throwable;
T invoke(String methodName, Object[] args, Class<T> returnType) throws Throwable;
}
```
```java
public class DefaultFeignClient<T> implements FeignClient<T> {
private Feign.Builder feignBuilder;
private Class<T> clazz;
public DefaultFeignClient(Feign.Builder feignBuilder, Class<T> clazz) {
this.feignBuilder = feignBuilder;
this.clazz = clazz;
}
@Override
public T invoke(Object[] args, Class<T> returnType) throws Throwable {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("invoke")) {
continue;
}
if (method.getParameterTypes().length != args.length) {
continue;
}
return invoke(method.getName(), args, returnType);
}
throw new RuntimeException("Cannot find suitable method to invoke in feign client!");
}
@Override
public T invoke(String methodName, Object[] args, Class<T> returnType) throws Throwable {
Method method = clazz.getDeclaredMethod(methodName, getParameterTypes(args));
Feign.Builder builder = feignBuilder;
builder.target(clazz, "http://localhost:8080");
Object result = method.invoke(builder.build(), args);
return (T) result;
}
private Class<?>[] getParameterTypes(Object[] args) {
Class<?>[] parameterTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
parameterTypes[i] = args[i].getClass();
}
return parameterTypes;
}
}
```
4. 实现Feign客户端工厂
```java
@Component
public class FeignClientFactory {
private Map<String, FeignClient<?>> feignClients;
public FeignClientFactory() {
feignClients = new HashMap<>();
}
public synchronized <T> void registerFeignClient(String serviceName, Feign.Builder feignBuilder, Class<T> clazz) {
FeignClient<T> feignClient = new DefaultFeignClient<>(feignBuilder, clazz);
feignClients.put(serviceName, feignClient);
}
public <T> FeignClient<T> getFeignClient(String serviceName) {
return (FeignClient<T>) feignClients.get(serviceName);
}
}
```
5. 使用FeignInterface注解
```java
@FeignInterface(serviceName = "user-service")
public interface IUserServiceFeign {
@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
User getUser(@PathVariable("id") Long id);
@RequestMapping(value = "/users", method = RequestMethod.POST)
User createUser(@RequestBody User user);
}
```
6. 在数据库Mapper中使用
```java
@Repository
public interface UserMapper {
@FeignInterface(serviceName = "user-service")
@Select("SELECT * FROM user WHERE id = #{id}")
User selectUserById(Long id);
@FeignInterface(serviceName = "user-service")
@Insert("INSERT INTO user(id, name) VALUES(#{id}, #{name})")
void insertUser(User user);
}
```
这样,您就可以使用AOP注解的方法实现数据库Mapper层的每个方法调用改为微服务Feign调用,并使用反射解决多个Feign方法的入参和返参不同的问题了。
阅读全文