- 简化我们的操作
- 代码好不好,评判标准:设计原则
- 代码一开始开发时,策略模式定义接口
- 代码成型后,设计模式解决问题,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;
}
}