利用AOP和反射实现Name的赋值

举个例子,每次查询订单时候,订单表内有订单号orderCode、支付编号payCode、用户编号userCode,但是查询时候需要显示支付的中文名payName和用户名
在分库时,就不能进行关联查询,如果每次遇到类似的都进行set,代码会很多很难看。这时候就可以使用AOP的方式进行赋值了

用户类

public class User {

    private String code;

    private String name;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

用户service

@Service
public class UserService {

    Map<String, User> userMap = new HashMap<>();
    List<User> userList = new ArrayList<>();

    public User getByCode(String code) {
        if (userMap.size() == 0) {
            defaultMap();
        }
        return userMap.get(code);
    }

    private void defaultMap() {
        defalutList();
        for (User user : userList) {
            userMap.put(user.getCode(), user);
        }
    }

    private void defalutList() {
        User user1 = new User();
        user1.setCode("c01");
        user1.setName("N01");
        userList.add(user1);
        user1 = new User();
        user1.setCode("c02");
        user1.setName("N02");
        userList.add(user1);
        user1 = new User();
        user1.setCode("c03");
        user1.setName("N03");
        userList.add(user1);
    }
}

支付类

public class Pay {
    private String code;

    private String name;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

支付service

@Service
public class PayService {

    Map<String, Pay> payMap = new HashMap<>();
    List<Pay> payList = new ArrayList<>();

    public Pay getByCode(String code) {
        if (payMap.size() == 0) {
            defaultMap();
        }
        return payMap.get(code);
    }

    private void defaultMap() {
        defalutList();
        for (Pay pay : payList) {
            payMap.put(pay.getCode(), pay);
        }
    }

    private void defalutList() {
        Pay pay1 = new Pay();
        pay1.setCode("p01");
        pay1.setName("ZFB");
        payList.add(pay1);
        pay1 = new Pay();
        pay1.setCode("p02");
        pay1.setName("WX");
        payList.add(pay1);
    }
}

使用在属性上的注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SetField {

    Class beanClass();

    String param();

    String method();

    String targetFiled();
}

使用在方法上的注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SetFieldValue {
}

订单类

public class Order {
    private String orderCode;

    private String userCode;

    @SetField(beanClass = UserService.class, param = "userCode", method = "getByCode", targetFiled = "name")
    private String userName;

    private String payCode;

    @SetField(beanClass = PayService.class, param = "payCode", method = "getByCode", targetFiled = "name")
    private String payName;

    @Override
    public String toString() {
        return orderCode + ":" + userCode + ":" + userName + ":" + payCode + ":" + payName;
    }

    public String getOrderCode() {
        return orderCode;
    }

    public void setOrderCode(String orderCode) {
        this.orderCode = orderCode;
    }

    public String getUserCode() {
        return userCode;
    }

    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPayCode() {
        return payCode;
    }

    public void setPayCode(String payCode) {
        this.payCode = payCode;
    }

    public String getPayName() {
        return payName;
    }

    public void setPayName(String payName) {
        this.payName = payName;
    }
}

订单service

@Service
public class OrderService {

    List<Order> orderList = null;
    Map<String, Order> orderMap = null;

    @SetFieldValue
    public List<Order> listOrders() {
        if (orderList == null) {
            defaultList();
        }
        return orderList;
    }

    @SetFieldValue
    public Order[] getOrders() {
        if (orderList == null) {
            defaultList();
        }
        Order[] result = new Order[orderList.size()];
        orderList.toArray(result);
        return result;
    }

    @SetFieldValue
    public Order getByCode(String code) {
        if (orderMap == null) {
            defaultMap();
        }
        return orderMap.get(code);
    }

    private void defaultMap() {
        if (orderList == null) {
            defaultList();
        }
        orderMap = new HashMap<>();
        for (Order order : orderList) {
            orderMap.put(order.getOrderCode(), order);
        }
    }

    private void defaultList() {
        orderList = new ArrayList<>();
        Order order = new Order();
        order.setOrderCode("c0001");
        order.setUserCode("c01");
        order.setPayCode("p01");
        orderList.add(order);
        order = new Order();
        order.setOrderCode("c0002");
        order.setUserCode("c02");
        order.setPayCode("p01");
        orderList.add(order);
        order = new Order();
        order.setOrderCode("c0003");
        order.setUserCode("c01");
        order.setPayCode("p02");
        orderList.add(order);
    }

}

切面

@Aspect
@Component
public class MyAspectField {

    @Autowired
    BeanUtil beanUtil;

    @Around("@annotation(com.sendinfo.module.test.test200218.SetFieldValue)")
    public Object doSetFieldValue(ProceedingJoinPoint pjp) throws Throwable {
        Object result = pjp.proceed();
        beanUtil.doSetFieldValue(result);
        return result;
    }
}

具体实现

@Component
public class BeanUtil {
    @Autowired
    ApplicationContext applicationContext;

    public void doSetFieldValue(Object result) throws Throwable {
        if (result == null) {
            return;
        }
        //获取对象类
        Class clazz = null;
        Object[] array = null;
        if (result instanceof Collection) {
            if (((Collection) result).isEmpty()) {
                //集合长度为0
                return;
            }
            clazz = ((Collection) result).iterator().next().getClass();
        } else {
            clazz = result.getClass();
            if (clazz.isArray()) {
                array = (Object[]) result;
                if (array.length == 0) {
                    return;
                }
                clazz = array[0].getClass();
            }
        }
        Field[] fields = clazz.getDeclaredFields();
        //做个简单的缓存map
        Map<Object, Object> map = new HashMap<>();
        for (Field field : fields) {
            //拿到字段的注解
            SetField sf = field.getAnnotation(SetField.class);
            //没有对应注解时,说明不需要
            if (sf == null) {
                continue;
            }
            //这个字段需要赋值
            field.setAccessible(true);
            //我需要调哪个接口
            Object mthodClass = applicationContext.getBean(sf.beanClass());
            //我的入参Field
            Field paramField = clazz.getDeclaredField(sf.param());
            //获得接口的具体方法
            Method method = sf.beanClass().getMethod(sf.method(), paramField.getType());
            //我需要拿到入参的值
            paramField.setAccessible(true);
            //出参的Field
            Field targetField = null;
            if (result instanceof Collection) {
                //遍历对象
                for (Object o : ((Collection) result)) {
                    setValue(o, paramField, method, mthodClass, targetField, field, sf, map);
                }
            } else {
                if (array == null) {
                    setValue(result, paramField, method, mthodClass, targetField, field, sf, map);
                } else {
                    //数组
                    for (Object o : array) {
                        setValue(o, paramField, method, mthodClass, targetField, field, sf, map);
                    }
                }
            }
        }
    }


    /**
     * @param o           修改的对象
     * @param paramField  入参的field
     * @param method      执行的方法
     * @param mthodClass  哪个接口对象去执行
     * @param targetField 目标的field
     * @param field       对象的field
     * @param sf          SetField注解的值
     * @param map         缓存
     * @throws Throwable
     */
    private void setValue(Object o, Field paramField, Method method, Object mthodClass, Field targetField, Field field, SetField sf, Map<Object, Object> map) throws Throwable {
        //获取入参值
        Object paramValue = paramField.get(o);
        //没有入参,那就算了
        if (paramValue == null) {
            return;
        }
        //先拿缓存
        String key = paramField.getName() + ":" + paramValue;
        Object value = map.get(key);
        if (value == null) {
            //这个对象是接口返回对象
            value = method.invoke(mthodClass, paramValue);
            if (value != null) {
                if (targetField == null) {
                    targetField = value.getClass().getDeclaredField(sf.targetFiled());
                    //目标可修改
                    targetField.setAccessible(true);
                }
                //只需要拿到对应的字段就行
                value = targetField.get(value);
                map.put(key, value);
            }
        }
        field.set(o, value);
    }
}

测试

@ComponentScan("com.sendinfo.module.test.test200218")
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

}

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext act = new AnnotationConfigApplicationContext(AppConfig.class);
        OrderService orderService = act.getBean(OrderService.class);
        Order[] ordersss = orderService.getOrders();
        System.out.println(Arrays.toString(ordersss));
        List<Order> orders = orderService.listOrders();
        System.out.println(orders);
        System.out.println(orderService.getByCode("c0001"));
        System.out.println(orderService.getByCode("c0004"));
    }
}

结果:

[c0001:c01:N01:p01:ZFB, c0002:c02:N02:p01:ZFB, c0003:c01:N01:p02:WX]
[c0001:c01:N01:p01:ZFB, c0002:c02:N02:p01:ZFB, c0003:c01:N01:p02:WX]
c0001:c01:N01:p01:ZFB
null
发布了148 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_33321609/article/details/104397165