註解簡單來講就是配置,是特別的配置,以前經常使用的配置文件,能夠用註解替換。而後經過反射去獲取註解的信息。java
你在IDE中新建一個註解定義,是這樣的結構的:spring
package com.nicchagil.exercise.springbootexercise.annotation; public @interface MyFirstAnnotation { }
而後大概有4個對上述結構加上一些配置,固然,這配置是以註解的形式添加的=_=!springboot
此註解會應用的哪裏,可經過以下配置:
app
保留到何時:
工具
@Documentedthis
@Inherited日誌
咱們先定義一個註解:code
package com.nicchagil.exercise.springbootexercise.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PojoPostProcessing { public Class targetClass(); public String[] whiteProperties(); }
使用註解,好比這裏我設置到一個方法上:對象
@PojoPostProcessing(targetClass=User.class, whiteProperties={"name"}) public List<User> selectXxx(String id) { ...... }
反射獲取註解的信息:blog
@Test public void test() throws NoSuchMethodException, SecurityException, ClassNotFoundException { Class clazz = Class.forName("com.nicchagil.exercise.springbootexercise.service.UserService"); Method method = clazz.getMethod("selectXxx", String.class); boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class); if (!isAnnotationPresent) { return; } PojoPostProcessing dpp = (PojoPostProcessing)method.getAnnotation(PojoPostProcessing.class); this.logger.info("dpp : {}", dpp); }
日誌:
dpp : @com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing(targetClass=class com.nicchagil.exercise.springbootexercise.mapper.entity.User, whiteProperties=[name])
好比如下就是在Spring AOP中攔截到方法,經過JoinPoint
獲取反射的Method
,而後看是否有指定註解,若是有註解,後面就是關於此註解要作的業務邏輯了:
package com.nicchagil.exercise.springbootexercise.aop; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing; @Aspect @Configuration public class ServiceControllerLogAop { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Pointcut("execution(* com.nicchagil.exercise.springbootexercise.service.*Service.*(..))") public void myPointcut() { } @AfterReturning("myPointcut()") public void myBefore(JoinPoint joinPoint) { /* 獲取方法對象 */ Signature signature = joinPoint.getSignature(); if (signature == null && !(signature instanceof MethodSignature)) { return; } MethodSignature methodSignature = (MethodSignature)signature; Method method = methodSignature.getMethod(); /* 是否有指定註解 */ boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class); if (!isAnnotationPresent) { return; } /* 獲取註解信息 */ PojoPostProcessing dpp = (PojoPostProcessing)method.getAnnotation(PojoPostProcessing.class); this.logger.info("dpp : {}", dpp); } }
將屬性置空的工具類:
package com.nicchagil.exercise.springbootexercise.util; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.core.MethodParameter; public class BeanClearUtils { private static Logger logger = LoggerFactory.getLogger(BeanClearUtils.class); public static void clearProperty(Object obj, String[] whiteProperty) { List<PropertyDescriptor> clearList = BeanClearUtils.getClearProperty(obj.getClass(), whiteProperty); try { for (PropertyDescriptor pd : clearList) { MethodParameter mp = BeanUtils.getWriteMethodParameter(pd); Method method = mp.getMethod(); method.invoke(obj, new Object[] {null}); } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException("設置空屬性失敗", e); } } /** * 獲取須要清除的字段列表 */ public static List<PropertyDescriptor> getClearProperty(Class<?> clazz, String[] whiteProperty) { PropertyDescriptor[] allPropertyDescriptor = BeanUtils.getPropertyDescriptors(clazz); /* 需保留的字段 */ Set<String> whitePropertySet = new HashSet<String>(Arrays.asList(whiteProperty)); whitePropertySet.add("class"); // 此字段無須清除 /* 需清除的字段 */ List<PropertyDescriptor> clearList = new ArrayList<PropertyDescriptor>(); for (PropertyDescriptor propertyDescriptor : allPropertyDescriptor) { if (!whitePropertySet.contains(propertyDescriptor.getName())) { clearList.add(propertyDescriptor); } } return clearList; } }
定義註解:
package com.nicchagil.exercise.springbootexercise.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PojoPostProcessing { public String[] whiteProperties(); }
處理註解邏輯:
package com.nicchagil.exercise.springbootexercise.aop; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import com.nicchagil.exercise.springbootexercise.annotation.PojoPostProcessing; import com.nicchagil.exercise.springbootexercise.util.BeanClearUtils; @Aspect @Configuration public class BeanPropertyFilterAop { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Pointcut("execution(* com.nicchagil.exercise.springbootexercise.service.*Service.*(..))") public void myPojoPostProcessingPointcut() { } @AfterReturning(value = "myPojoPostProcessingPointcut()", returning = "returnObject") public void myAfter(JoinPoint joinPoint, Object returnObject) { /* 獲取方法對象 */ Signature signature = joinPoint.getSignature(); if (signature == null && !(signature instanceof MethodSignature)) { return; } MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); /* 是否有指定註解 */ boolean isAnnotationPresent = method.isAnnotationPresent(PojoPostProcessing.class); if (!isAnnotationPresent) { return; } /* 獲取註解信息 */ PojoPostProcessing dpp = (PojoPostProcessing) method.getAnnotation(PojoPostProcessing.class); this.logger.info("dpp : {}", dpp); /* 只保留bean的指定屬性值(其它屬性值置空) */ logger.info("before bean : {}", returnObject); BeanClearUtils.clearProperty(returnObject, dpp.whiteProperties()); logger.info("after bean : {}", returnObject); } }
使用註解:
@PojoPostProcessing(whiteProperties={"name", "createTime"})