zoukankan      html  css  js  c++  java
  • 【Java基础】Java注解简单入门

    注解简单来说就是配置,是特别的配置,之前常用的配置文件,可以用注解替换。然后通过反射去获取注解的信息。

    如何定义一个注解

    你在IDE中新建一个注解定义,是这样的结构的:

    package com.nicchagil.exercise.springbootexercise.annotation;
    
    public @interface MyFirstAnnotation {
    
    }
    

    然后大概有4个对上述结构加上一些配置,当然,这配置是以注解的形式添加的=_=!

    此注解使用在哪里

    此注解会应用的哪里,可通过如下配置:

    保留在什么时候

    保留到什么时候:

    注解体现在文档中

    @Documented

    子类是否继承父类的注解

    @Inherited

    用反射获取注解的信息

    我们先定义一个注解:

    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) {
    		......
    	}
    

    反射获取注解的信息:

    	@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"})
    
  • 相关阅读:
    三、nginx 编译参数
    二、nginx 安装目录详解
    一、nginx 安装
    CSS未知宽高元素水平垂直居中
    w3c标准盒模型与IE传统模型的区别
    JavaScript设计模式与开发实践:分时函数
    JavaScript设计模式与开发实践:惰性函数
    那些年,前端路上遇到的浏览器兼容问题(一)
    css3的filter属性
    关于Normalize.css
  • 原文地址:https://www.cnblogs.com/nick-huang/p/8151259.html
Copyright © 2011-2022 走看看