Skip to content

Latest commit

 

History

History
148 lines (119 loc) · 4.43 KB

自定义业务封装.md

File metadata and controls

148 lines (119 loc) · 4.43 KB

自定义业务封装

  • 简化我们的操作
  • 代码好不好,评判标准:设计原则
  • 代码一开始开发时,策略模式定义接口
  • 代码成型后,设计模式解决问题,AOP

通用的获取和设置组件

  • 实现思路:

    • 注解,能让类附上说明消息到运行期,给机器看的,普通注释编译生成class就没有了
    • 在注解上标注要调用的信息,通过aop获取需要的消息
  • 解决的问题

    • 哪些属性需要设置(带有指定注解的属性)
    • 调用哪个bean的哪个方法(注解的说明项指定)
    • 要传入的值作为参数(注解的说明项指定)
    • 要获取到得到的对象上的哪个属性的值(注解的说明项指定)
  • 代码实现

/**
 * 标记需要设置属性值的属性,将目标对象的值设置到该属性上
 *
 * @author dongtangqiang
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedSetValue {

    /**
     * 调用的bean
     */
    Class<?> beanClass();

    /**
     * 调用的方法
     */
    String method();

    /**
     * 传入的值作为参数
     */
    String param();

    /**
     * 获取到的目标对象的哪个属性值
     */
    String targetField();
}
/**
 * @author dongtangqiang
 */
@Component
public class BeanUtil implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    /**
     * 遍历集合设置集合中对象的属性值,利用反射机制
     *
     * @param coll
     * @throws Exception
     */
    public void setFiledValueForColl(Collection coll) throws Exception {
        // [{"id":1,"customerId":1000,"customerName":null}]
        // 获取注解 -- method名字
        // 反射调用method.invoke() -- 获取到User对象 -- 获取name属性 -- 设置到结果集

        // Order对象
        Class<?> clazz = coll.iterator().next().getClass();
        // Order对象的属性
        Field[] fields = clazz.getDeclaredFields();

        // 缓存
        Map<String, Object> cache = new HashMap<>();

        for (Field needField : fields) {
            // 获取注解
            NeedSetValue nsv = needField.getAnnotation(NeedSetValue.class);
            if (nsv == null) {
                continue;
            }

            // 设置该属性可见
            needField.setAccessible(true);

            Object bean = this.applicationContext.getBean(nsv.beanClass());

            // public com.olive.springboot.start.model.User com.olive.springboot.start.service.UserServiceImpl.findById(java.lang.Long)
            Method method = nsv.beanClass().getMethod(nsv.method(), clazz.getDeclaredField(nsv.param()).getType());

            // class com.olive.springboot.start.model.Order
            Field paramField = clazz.getDeclaredField(nsv.param());
            paramField.setAccessible(true);

            Field targetField = null;
            boolean needInnerField = StringUtils.isNotEmpty(nsv.targetField());
            String keyPrefix = nsv.beanClass() + "-" + nsv.method() + "-" + nsv.targetField() + "-";

            // 循环结果集
            for (Object obj : coll) {
                // 入参的具体值
                Object paramValue = paramField.get(obj);
                if (paramValue == null) {
                    continue;
                }

                Object value = null;
                String key = keyPrefix + paramValue;

                if (cache.containsKey(key)) {
                    value = cache.get(key);
                } else {
                    // value是一个User对象
                    value = method.invoke(bean, paramValue);
                    if (needInnerField) {
                        if (value != null) {
                            if (targetField == null) {
                                targetField = value.getClass().getDeclaredField(nsv.targetField());
                                targetField.setAccessible(true);
                            }
                            // User name的具体值
                            value = targetField.get(value);
                        }
                    }

                    cache.put(key, value);
                }

                // 设置值
                needField.set(obj, value);
            }
        }

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}