举个例子,每次查询订单时候,订单表内有订单号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