java aop改变方法返回值_Aop AfterReturning增强方法返回值
需求:查询订单要返回用户名
为了解耦,查询订单中不查询用户,使用aop自动注入用户名
注意:订单列表中的用户缓存到了内存,遍历查询很快,如果直接查数据库,则效率相对低
思路:对返回值加强(aop对返回值增强,向订单表中注入userName)
1.注解
/*** 设置属性非空的开关
* 只有方法上加上此注解,才会对Field上加上 FieldNotNull 的属性赋值*/@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)public @interfaceSetFieldSwitch {
}
/*** 字段非空注解*/@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)//作用在字段上(告诉aop去哪个object调用哪个method,需要传什么param参数,查询的结果需要取哪一个targetField)
public @interfaceFieldNotNull {
Class beanClass();//需要去哪个class中调用 (userName的属性从)
String method();//需要调用class中的哪个方法
String param();//调用方法的参数
String targetField();//调用方法后需要哪个值(为了set到添加该注解的属性上)
}
2:订单+用户对象
@Datapublic class UserOrder /*extends Order*/{privateInteger id;privateInteger goodsId;privateInteger userId;
@FieldNotNull(beanClass= UserCache.class, method = “get”, param = “userId”, targetField = “realName”)private String userName; //用户名
private String goodName; //物品名称
publicUserOrder(Integer id, Integer userId, Integer goodId, String userName, String goodName) {this.userName =userName;this.goodName =goodName;this.setId(id);this.setUserId(userId);this.setGoodsId(goodId);
}
}
3:查询订单方法
@Servicepublic classOrderService {
@AutowiredprivateOrderDao orderDao;
@SetFieldSwitch // 开启aop增强(如果不开启,则FileNotNull注解不会起作用),将控制与实现分开)public ListlistOrder() {returnorderDao.listOrder();
}
}
4:查询用户的方法
/*** 模拟用户的缓存*/@Componentpublic classUserCache {
@AutowiredprivateUserDao userDao ;private static Map userCache = new HashMap<>();public voidput(Integer userId, User user) {
userCache.put(userId, user);
}publicUser get(Integer userId) {
User user=userCache.get(userId);if (user == null) {
user=userDao.getById(userId);if (user==null) return null;
userCache.put(userId,user);
}returnuser;
}public booleancontain(Integer userId) {returnuserCache.containsKey(userId);
}
}
5:aop切面
使用AfterReturning
/***
*@parampoint 切点
*@paramobj 返回值
*@return*@throwsThrowable*/@AfterReturning(value = “setFieldValuePoint()”, returning = “obj”)public Object setValue(JoinPoint point, Object obj) throwsThrowable {
this.setFieldValueForCollection((Collection) obj);returnobj;
}
6:使用反射+注解 赋值
/*** 查询并赋值操作
*
*@paramcollection*/
private void setFieldValueForCollection(Collection collection) throwsException {if (collection == null || collection.size() == 0) return;
Iterator iterator=collection.iterator();
Object next=iterator.next();/*collection中userOrder元素对应的class*/Class clazz = next.getClass(); // class com.draymond.aop.query.UserOrder/*获取userOrder中所有的属性*/
Field[] declaredFields = clazz.getDeclaredFields();
for(Field field : declaredFields) {/*—————- 获取 哪个class 调用哪个 method ,需要什么paras —————-*/
/*获取userOrder属性上的FieldNotNull注解(其他 Field 也可以有其他注解)*/FieldNotNull annotation = field.getAnnotation(FieldNotNull.class);if (annotation == null) continue;
field.setAccessible(true); //暴力拆解
Class beanClass =annotation.beanClass();
String method=annotation.method(); // get(注解上的值)
String param=annotation.param(); // userId
String targetField=annotation.targetField(); // realName
Field paraField= clazz.getDeclaredField(param); //获取方法需要的参数值(paraField.get(user)中获取)
paraField.setAccessible(true);
Method methodExecute=beanClass.getDeclaredMethod(method, paraField.getType());/*从spring上下文获取beanClass对应的bean*/Object userCache = applicationContext.getBean(beanClass);//for循环,对list中每个user的带FieldNotNull注解的属性赋值
for (Object userOrder : collection) { //list上的每条user对象
Object user = methodExecute.invoke(userCache, paraField.get(userOrder)); // 执行 UserCache 中的 get 方法,需要的参数值 paraField if (user == null) continue;
Field targetFieldValue= user.getClass().getDeclaredField(targetField); //获取user对象中的 targetField 的值
if (targetFieldValue == null) continue;
targetFieldValue.setAccessible(true);
field.set(userOrder, targetFieldValue.get(user));//将 user中的targetField(realName) 的值,set到userOrder对象中的 userName
}
}
}
其他
/*** 模拟从数据库中查询订单*/@Componentpublic classOrderDao {public ListlistOrder() {
UserOrder userOrder1= new UserOrder(1, 1, 1, “zsc”, “电冰箱”);
UserOrder userOrder2= new UserOrder(2, 1, 2, null, “洗衣机”);
UserOrder userOrder3= new UserOrder(3, 1, 3, null, “java Thread”);List list= newArrayList();
list.add(userOrder1);
list.add(userOrder2);
list.add(userOrder3);returnlist;
}publicUserOrder getById(Integer id) {return listOrder().stream().filter(userOrder -> userOrder.getId() == id).findFirst().orElse(null);
}
}
方法上使用注解开启增强
@Servicepublic classOrderService {
@AutowiredprivateOrderDao orderDao;
@SetFieldSwitchpublic ListlistOrder() {returnorderDao.listOrder();
}publicUserOrder getOrderById(Integer id) {returnorderDao.getById(id);
}
}
未增强效果
[{“id”:1,”goodsId”:1,”userId”:1,”userName”:”zsc”,”goodName”:”电冰箱”}, // 模拟数据的时候就赋值了
{“id”:2,”goodsId”:2,”userId”:2,”userName”:null,”goodName”:”洗衣机”},
{“id”:3,”goodsId”:3,”userId”:1,”userName”:null,”goodName”:”java Thread”}]
增强效果
[{“id”:1,”goodsId”:1,”userId”:1,”userName”:”zsc”,”goodName”:”电冰箱”},
{“id”:2,”goodsId”:2,”userId”:2,”userName”:”draymond”,”goodName”:”洗衣机”},
{“id”:3,”goodsId”:3,”userId”:1,”userName”:”zsc”,”goodName”:”java Thread”}]
还没有评论,来说两句吧...