Spring 注解学习

分类

  1. Spring的bean容器相关

@Required @Autowired @PostConstruct @PreDestory

@Inject @Named @Qualifer @Provider @Scope @Singleton

  1. springmvc 相关
  @Controller @RequestMapping @RequestParam @ResponseBody 等
  1. 类注解
    1. @Component、@Repository、@Controller、@Service @ManagedBean和@Named

都是添加在类上面的类级别注解

Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IoC容器中

2.类内部注解

@Autowire、@Value、@Resource

都是在类内部的字段或者方法上的类内部注解

SpringIoC容器通过Bean后置注解处理器解析Bean内部的注解

1. 注解分析

基于java的接口进行实现,是一种特殊的接口类型,通常对于注解来说,三种情况

RetentionPolicy�

  1. SOURCE�
    1. 在编译前就会被丢弃
  2. CLASS�
    1. 编译后留在class中
  3. RUNTIME��
    1. 一直存在,运行的时候注解也会被保留

2. Autowired�

  • 包名

package org.springframework.beans.factory.annotation;

  • 定义
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}
  • �作用

@Autowired常用来作属性的注入,可以作用在构造方法、普通方法、字段、注解、参数上。

Spring中 AutowiredAnnotationBeanPostProcessor 处理器负责处理@Autowired注解相关注入。

  • 使用
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAutowired {
}
public class Student {

    @MyAutowired
    public Money money;

    public void show(){
        System.out.println(money.moneyCount+"Student say");
    }
}
public class Money {
    public int moneyCount = 300;
}
public class Application {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        SpringApplication.run(Application.class, args);


        Student a = new Student();
        Class<? extends Student> clazz = a.getClass();
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            MyAutowired myAutowired = field.getAnnotation(MyAutowired.class);
            if (myAutowired != null) {
                Class fieldClass = field.getType();  // 在这里就是B.class
                Money b = (Money) fieldClass.newInstance();
                field.set(a, b);
            }
        }

        a.show();

    }

}

2. 自定义注解解析

  1. 拦截器解析
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
    boolean required() default true;
}

@Component
    public class MyTestInterceptor implements HandlerInterceptor {

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("执行了拦截器……");
            if (!(handler instanceof HandlerMethod)){
                return true;
            }
            Method method = ((HandlerMethod) handler).getMethod();
            MyTest annotation = method.getAnnotation(MyTest.class);

            if (annotation != null){
                boolean required = annotation.required();
                if (required) {
                    //业务逻辑处理
                }
            }
            return true;
        }

        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        }

        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        }
    }
@Configuration
public class ApiConfig extends WebMvcConfigurationSupport {

    @Autowired
    private MyTestInterceptor myTestInterceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.myTestInterceptor).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

}
  1. AOP 解析
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
    boolean required() default true;
}
@Component
@Aspect
public class MyTestAspect {


    @Pointcut("@annotation(com.wyc.MyTest)")
    private void pointCut(){ }

    @Around("pointCut()")
    public void advice(JoinPoint joinPoint){
        System.out.println("执行了切面……");
    }

//    @Before("pointCut()")
//    public void before(JoinPoint joinPoint){
//        System.out.println("执行了切面……");
//        //业务逻辑处理……
//    }
}

3. @ApiVersion�

  • 需求

对同一个API接口进行多版本的管理

  • 方案
    1. 不对API进行版本管理

每次版本升级都强制用户更新升级

2. 不同版本用不同域名

针对域名转发到部署了不同版本应用的服务器,http://v1.com ,v2.com,http://v3.com 的域名分别转发到部署了对应版本的应用服务器

3. 维护多个版本的代码

在代码里面维护多个版本的API,保存多个版本的接口

  • 思路
    1. 通过注解来标识不同接口的版本
    2. 通过URL和请求Header 里面的apiversion值来建立与Controller不同版本方法的关系
    3. 根据URL+apiversion 来执行对应版本的Controller方法
  • 实现
    • 定义注解
    • 实现 RequestCondition� 定义排序对象
    • 重新定义Handler通过继承RequestMappingHandlerMapping,重写getCustomTypeCondition(Class<?> handlerType)和getCustomMethodCondition(Method method)方法
    • 把自定义的RequestMappingHandlerMapping设置成默认的HandlerMapping交给spring管理,通过继承WebMvcConfigurationSupport 重写requestMappingHandlerMapping()方法
    • 待完善
@RequestMapping("/wyc")
@RestController
//@ApiVersion("1")
public class TestAPIVersionController {

    @GetMapping("/hello")
    @ApiVersion(1)
    public String hello1(){
        return "version 1";
    }

    @GetMapping("/hello")
    @ApiVersion(2)
    public String hello2(){
        return "version 2";
    }

    @RequestMapping("/hello")
    @ApiVersion(3)
    public String hello3(){
        return "version 3";
    }

}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface ApiVersion {
    int value();
}
public class ApiRequestCondition implements RequestCondition<ApiRequestCondition> {

    private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile(".*v(\\d+).*");

    private int apiVersion;

    public ApiRequestCondition(int apiVersion){
        this.apiVersion = apiVersion;
    }
    public  int getApiVersion(){
        return apiVersion;
    }

    @Override
    public ApiRequestCondition combine(ApiRequestCondition other) {
        return new ApiRequestCondition(other.getApiVersion());
    }

    @Override
    public ApiRequestCondition getMatchingCondition(HttpServletRequest request) {
        //默认版本号 请求错误时使用最新版本号
        Integer version = 9999;
        String murl = request.getRequestURI();
        String apiversion = request.getHeader("apiversion");
        System.out.println(murl);
        if(!StringUtils.isEmpty(apiversion)){
            Matcher m = Pattern.compile("v(\\d+)").matcher(apiversion);
            Boolean status = m.find();
            if (status == true){
                version = Integer.valueOf(m.group(1));
            }
        }
        System.out.println("version:"+version+",apiVersion:"+this.apiVersion);
        //返回<=请求版本号的版本
        if (version <= this.apiVersion){

//            return this;
        }
        return null;
    }

    @Override
    public int compareTo(ApiRequestCondition other, HttpServletRequest request) {
        //对符合版本的版本号排序
        String reqver = request.getHeader("apiversion");
        System.out.println("compareTo-->other:"+other.getApiVersion()+",thisversion:"+this.apiVersion+",req-version:"+reqver);
        return other.getApiVersion() - this.apiVersion;
    }
}

public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    private static final String VERSION_FLAG = "{version}";

    private static RequestCondition<ApiRequestCondition> createCondition(ApiVersion apiVersion) {
//        RequestMapping classRequestMapping = clazz.getAnnotation(RequestMapping.class);
//        if (classRequestMapping == null) {
//            return null;
//        }
//        StringBuilder mappingUrlBuilder = new StringBuilder();
//        if (classRequestMapping.value().length > 0) {
//            mappingUrlBuilder.append(classRequestMapping.value()[0]);
//        }
//        String mappingUrl = mappingUrlBuilder.toString();
//        if (!mappingUrl.contains(VERSION_FLAG)) {
//            return null;
//        }
//        ApiVersion apiVersion = AnnotationUtils.findAnnotation(clazz, ApiVersion.class);
//        ApiVersion apiVersion = clazz.getAnnotation(ApiVersion.class);

        if(apiVersion == null){
//            return new ApiRequestCondition(1);
            return null;
        }
        System.out.println(" create apiVersion:"+ apiVersion.value());
        Integer currentval = apiVersion.value();
        ApiRequestCondition apiRequestCondition = new ApiRequestCondition(apiVersion.value());
//        ApiRequestCondition apiRequestCondition = apiVersion == null ? new ApiRequestCondition(1) : new ApiRequestCondition(apiVersion.value());
        return apiRequestCondition;
    }
    @Override
    protected RequestCondition<ApiRequestCondition> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
//        return createCondition(handlerType);
        return createCondition(apiVersion);
//        return super.getCustomTypeCondition(handlerType);
    }

    @Override
    protected RequestCondition<ApiRequestCondition> getCustomMethodCondition(Method method) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
//        return createCondition(method.getClass());
        return createCondition(apiVersion);
    }
//    private RequestCondition<ApiRequestCondition> createCondition(ApiVersion apiVersion) {
//        return apiVersion == null ? null : new ApiRequestCondition(apiVersion.value());
//    }
}

//@EnableSwagger2
@Configuration
@SuppressWarnings({"unused"})
class WebApiVesionConfig extends WebMvcConfigurationSupport {


    @Autowired
    private MyTestInterceptor myTestInterceptor;



    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.myTestInterceptor).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

    @Autowired
    public FormattingConversionService mvcConversionService;
    @Autowired
    public ResourceUrlProvider mvcResourceUrlProvider;


    @Override
    protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
        handlerMapping.setOrder(0);
        handlerMapping.setInterceptors(getInterceptors(mvcConversionService,mvcResourceUrlProvider));
        return handlerMapping;
//        return new CustomRequestMappingHandlerMapping();
    }

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping(ContentNegotiationManager contentNegotiationManager, FormattingConversionService conversionService, ResourceUrlProvider resourceUrlProvider) {
        return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider);
    }

posted @ 2024-12-17 15:51  若云  阅读(47)  评论(0)    收藏  举报