java aop改变方法返回值_Aop AfterReturning增强方法返回值

ゞ 浴缸里的玫瑰 2022-11-07 15:50 581阅读 0赞

需求:查询订单要返回用户名

为了解耦,查询订单中不查询用户,使用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”}]

发表评论

表情:
评论列表 (有 0 条评论,581人围观)

还没有评论,来说两句吧...

相关阅读