1.本文实现的是订单查询中属性字段(用户名称为空.)通过注解反射方法给customerName填充值。
package com.example.hello.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
/**
* 注解类
*/
public @interface NeedSetValueField {
Class<?> beanClass();
String param();
String method();
String targetField();
}
package com.example.hello.aspect;
import com.example.hello.util.BeanUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Component
@Aspect
public class SetFieldValueAspect {
@Autowired
BeanUtil beanUtil;
/**
* 切面编程环绕执行
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("@annotation(com.example.hello.annotation.NeedSetValue)")
public Object doSetValue(ProceedingJoinPoint joinPoint)throws Throwable{
Object result = joinPoint.proceed();
// 操作结果集,得值进行设置
beanUtil.setValueByCol((Collection) result);
return result;
}
}
package com.example.hello.controller;
import com.example.hello.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 分页查询order
* @param customerId
* @param pageNum
* @param pageSize
* @return
* @throws Exception
*/
@RequestMapping("query")
public Object query(String customerId, int pageNum, int pageSize)throws Exception{
return this.orderService.pageQuery(customerId,pageNum,pageSize);
}
}
package com.example.hello.controller;
import com.example.hello.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 分页查询order
* @param customerId
* @param pageNum
* @param pageSize
* @return
* @throws Exception
*/
@RequestMapping("query")
public Object query(String customerId, int pageNum, int pageSize)throws Exception{
return this.orderService.pageQuery(customerId,pageNum,pageSize);
}
}
package com.example.hello.dao;
import com.example.hello.model.User;
import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.cache.annotation.Cacheable;
import java.util.List;
@Cacheable
public class UserDao {
void insert(User u) {
}
void update(User u){}
/**
* 查询用户列表
* @param username
* @return
*/
List<User> query( String username){
return null;
}
/**
* 根据id查询用户
* @param id
* @return
*/
User find(String id){
User user = new User("1","1");
return user ;
}
}
package com.example.hello.model;
import com.example.hello.annotation.NeedSetValueField;
import com.example.hello.dao.UserDao;
import java.io.Serializable;
public class Order implements Serializable {
/**
* list={id:1,cid:1,cname:null}
*/
private static final long serialVersion = 100000000L;
private String id;
private String customerId;
/**
* 通过注解实现给customerName赋值
*/
@NeedSetValueField(beanClass = UserDao.class,param = "customerId",method = "find",targetField = "name")
private String customerName; //set值 后置方法---反射 user--find-->method.invoke()--->name---获取到具体值
// --->set
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
}
package com.example.hello.model;
public class User {
private static final long serialVersion = 100000001L;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
public User(String id,String name){
this.id = id;
this.name = name;
}
}
package com.example.hello.service;
import com.example.hello.annotation.NeedSetValue;
import com.example.hello.dao.OrderDao;
import com.example.hello.model.Order;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
/**
* 1.获取和设置组件
* 2.首先,当调用组件时,我怎么知道设置哪些属性值
* 3,这个要告诉我
* 4.我怎么知道哪个bean的哪个方法,以及要传入的值
* 5.这个要告诉我
*/
@Autowired
private OrderDao orderDao;
// 执行本方法进行切面
// 自定义注解切面
@NeedSetValue
public Page<Order> pageQuery(String customerId, int pageNum, int pageSize)throws Exception{
Page<Order> page = PageHelper.startPage(pageNum,pageSize);
this.orderDao.query(customerId);
// 批量查询10条
// util --- setField(class bean,params,setField) ---可以解决问题
// 更加优雅的方法,不用改动原有的代码
// 使用AOP进行增强处理,对结果进行设置,再返回
// annotion 注解,能让类附上说明信息到运行期
return page;
}
}
package com.example.hello.util;
import com.example.hello.annotation.NeedSetValueField;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Component
public class BeanUtil implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext var1) throws BeansException{
this.applicationContext = applicationContext;
}
public void setValueByCol(Collection col)throws Exception{
Class<?> clazz = col.iterator().next().getClass();
Field[] fields = clazz.getDeclaredFields();
Map<String,Object> cache = new HashMap<>();
for (Field field: fields) {
NeedSetValueField sv = field.getAnnotation(NeedSetValueField.class); //拿到定义在属性上的注解
if (sv == null)continue;
field.setAccessible(true);
Object bean = this.applicationContext.getBean(sv.beanClass()); // 得到bean(UserDao)
// bean中找到方法 ---find方法
Method method = sv.beanClass().getMethod(sv.method(),clazz.getDeclaredField(sv.param()).getType());
// customerId
Field paramField = clazz.getDeclaredField(sv.param());
paramField.setAccessible(true);
Field targetField = null;
Boolean needInnerField = StringUtils.isNotEmpty(sv.targetField());
String keyPrefix = sv.beanClass()+"-"+sv.method()+"-"+sv.targetField()+"-";
for (Object obj:col) {
Object paramValue = paramField.get(obj); // 3
if (paramValue == null) continue;
Object value = null;
String key = keyPrefix;
if (cache.containsKey(key)){
value = cache.get(key);
}else {
value = method.invoke(bean,paramValue); // User == value
if (value != null){
if (needInnerField){
if (targetField == null){
targetField = value.getClass().getDeclaredField(sv.targetField());
}
value = targetField.get(value); // user中的名字tony
}
}
cache.put(key,value);
}
field.set(obj,value); //field ---customerName
}
// 参数具体的值
// method.invoke();
}
}
}
package com.example.hello;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHelloApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceHelloApplication.class, args);
}
@Value("${server.port}")
String port;
@RequestMapping("/hello")
public String home(@RequestParam(value = "name", defaultValue = "toher") String name) {
return "hi " + name + " ,this is Feign Project , i am from port:" + port;
}
}
项目结构: