java自定义注解以及原理

来源:互联网 发布:电脑硬件温度检测软件 编辑:程序博客网 时间:2024/06/05 16:26

自定义注解应用举例

在springmvcconfig中定义前置通知,代码如下:
import java.util.Arrays;import java.util.List;import com.puhui.flowplatform.manage.filter.RightFilter;import org.springframework.aop.BeforeAdvice;import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.util.ResourceUtils;import org.springframework.web.servlet.ViewResolver;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.support.config.FastJsonConfig;import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import com.puhui.flowplatform.manage.interceptor.BeforeControllerInterceptor;@Configurationpublic class SpringMvcConfig extends WebMvcConfigurerAdapter {    @Override    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {        super.configureMessageConverters(converters);        // 初始化转换器        FastJsonHttpMessageConverter fastConvert = new FastJsonHttpMessageConverter();        // 初始化一个转换器配置        FastJsonConfig fastJsonConfig = new FastJsonConfig();        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);        // 将配置设置给转换器并添加到HttpMessageConverter转换器列表中        fastConvert.setFastJsonConfig(fastJsonConfig);        converters.add(fastConvert);    }    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/swagger-ui.html").addResourceLocations(                ResourceUtils.CLASSPATH_URL_PREFIX + "/META-INF/resources/");        registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/static/",                ResourceUtils.CLASSPATH_URL_PREFIX + "/dist/static/");        registry.addResourceHandler("/page/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/dist/");        super.addResourceHandlers(registry);    }    @Bean    public ViewResolver viewResolver() {        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();        resolver.setCache(true);        resolver.setPrefix(ResourceUtils.CLASSPATH_URL_PREFIX + "templates/");        resolver.setSuffix(".ftl");        resolver.setContentType("text/html; charset=UTF-8");        return resolver;    }    // 创建Advice或Advisor    @Bean    public BeforeAdvice beforeControllerInterceptor() {        return new BeforeControllerInterceptor();    }    @Bean    public BeanNameAutoProxyCreator beanBeforeAutoProxyCreator() {        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();        beanNameAutoProxyCreator.setProxyTargetClass(true);        // 设置要创建代理的那些Bean的名字        beanNameAutoProxyCreator.setBeanNames("*Controller");        // 设置拦截链名字(这些拦截器是有先后顺序的)        beanNameAutoProxyCreator.setInterceptorNames("beforeControllerInterceptor");        return beanNameAutoProxyCreator;    }    @Bean(name = "rightFilter")    public FilterRegistrationBean  addRightFilter(){        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();        filterRegistrationBean.setFilter(new RightFilter());        filterRegistrationBean.setUrlPatterns(Arrays.asList("/api/*"));        return filterRegistrationBean;    }}

BeforeControllerInterceptor代码如下:
import java.lang.reflect.Method;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.aop.MethodBeforeAdvice;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.annotation.AnnotationUtils;import com.puhui.flowplatform.common.constants.MegCodeEnums.ResponseCodeEnum;import com.puhui.flowplatform.common.exception.ServiceException;import com.puhui.flowplatform.common.model.platform.User;import com.puhui.flowplatform.common.model.platform.app.AppRequestParam;import com.puhui.flowplatform.common.utils.CommonUtils;import com.puhui.flowplatform.manage.annotation.RequiredInterceptor;import com.puhui.flowplatform.manage.utils.RedisTemplateOperate;public class BeforeControllerInterceptor implements MethodBeforeAdvice {    private static final Logger log = LoggerFactory.getLogger(BeforeControllerInterceptor.class);    @Autowired    private RedisTemplateOperate redisTmp;    @SuppressWarnings("rawtypes")    @Override    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {        RequiredInterceptor requiredInterceptor = AnnotationUtils.findAnnotation(arg0, RequiredInterceptor.class);        if (requiredInterceptor != null) {            // 检验token            AppRequestParam appRequestParam = (AppRequestParam) arg1[0];            String token = appRequestParam.getComm().getToken();            if (!redisTmp.hasKey(token)) {                log.info("token:{}已经失效", token);                throw new ServiceException(ResponseCodeEnum.C808.getCode());            } else {                User user = CommonUtils.getCurUser(token);                if (null == user) {                    redisTmp.delete(token);                    log.error("token:{}已经失效", appRequestParam.toString());                    throw new ServiceException(ResponseCodeEnum.C808.getCode());                }            }        }    }}

Annotation定义如下

package com.puhui.flowplatform.manage.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)@Documentedpublic abstract @interface RequiredInterceptor {    boolean required() default true;}


1 自定义注解,采用@interface ,可以根据需求定义方法体
2 应用注解到要拦截到方法上

@RequiredInterceptor(required = true)
3. 拦截器进行拦截,发现方法定义了@requiredInterceptor 注解后,进行特定到业务逻辑判断

其实注解只是一个flag到作用,主要到拦截逻辑还是拦截器生效。
我们也可以定一个注解,检查权限,@requiredPermission,然后配置前置通知,在拦截器里面判断有这个注解到,进行权限校验。

public class BeforeControllerInterceptor implements MethodBeforeAdvice {    private static final Logger log = LoggerFactory.getLogger(BeforeControllerInterceptor.class);    @Autowired    private RedisTemplateOperate redisTmp;    @SuppressWarnings("rawtypes")    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {        RequiredInterceptor requiredInterceptor = AnnotationUtils.findAnnotation(arg0, RequiredInterceptor.class);        if (requiredInterceptor != null) {            // 检验token            AppRequestParam appRequestParam = (AppRequestParam) arg1[0];            String token = appRequestParam.getComm().getToken();            if (!redisTmp.hasKey(token)) {                log.info("token:{}已经失效", token);                throw new ServiceException(ResponseCodeEnum.C808.getCode());            } else {                User user = CommonUtils.getCurUser(token);                if (null == user) {                    redisTmp.delete(token);                    log.error("token:{}已经失效", appRequestParam.toString());                    throw new ServiceException(ResponseCodeEnum.C808.getCode());                }            }        }    }}

Method: 拦截到方法对象
public com.puhui.flowplatform.common.model.Response com.puhui.flowplatform.manage.controller.RoleController.getRolesList(java.lang.String,java.lang.String,javax.servlet.http.HttpServletRequest)
arg1:方法到参数,是一个数组,里面有方法到所有参数
arg2: 方法所在的对象

上述例子是通过spring提供的工具栏annotationUtil去查询是否有annotations。 也可以通过下面的方法:
public static void main(String[] args) {    try {    for (Method method : AnnotationParsing.class        .getClassLoader()        .loadClass(('com.journaldev.annotations.AnnotationExample'))        .getMethods()) {        // checks if MethodInfo annotation is present for the method        if (method.isAnnotationPresent(com.journaldev.annotations.MethodInfo.class)) {            try {        // iterates all the annotations available in the method                for (Annotation anno : method.getDeclaredAnnotations()) {                    System.out.println('Annotation in Method ''+ method + '' : ' + anno);                    }                MethodInfo methodAnno = method.getAnnotation(MethodInfo.class);                if (methodAnno.revision() == 1) {                    System.out.println('Method with revision no 1 = '+ method);                    }             } catch (Throwable ex) {                    ex.printStackTrace();                    }        }    }    } catch (SecurityException | ClassNotFoundException e) {            e.printStackTrace();         }    } }


 注解解释及原理


注解是标记,也可以理解成是一种应用在类、方法、参数、属性、构造器上的特殊修饰符。注解作用有以下三种:

       第一种:生成文档,常用的有@param@return等。

       第二种:替代配置文件的作用,尤其是在spring等一些框架中,使用注解可以大量的减少配置文件的数量。

       第三种:检查代码的格式,如@Override,标识某一个方法是否覆盖了它的父类的方法。


注解的底层也是使用反射实现的
原创粉丝点击