【Java基礎】Java註解簡單入門

註解簡單來講就是配置,是特別的配置,以前經常使用的配置文件,能夠用註解替換。而後經過反射去獲取註解的信息。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中解析註解,而後實體你註解須要作的業務

好比如下就是在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"})
相關文章
相關標籤/搜索