java jdk自带注解_Java原生注解和Spring注解的说明

注解

java 原生注解

Spring 中的注解

一 Java原生注解

Java注解是在JDK1.5以后引入的新特性!

有利于代码的解藕、整洁,提升开发的效率!通俗来讲,注解就是标签,标签的内容可以变动!

注解也是java中的一种数据类型!注解的创建和接口的创建很类似!使用@Interface修饰!

JDK本身自带的几种原生注解!也就是我们常说的元注解,原生注解是用于修饰自定义注解!JVM规范规定自定义注解必须使用些原生注解修饰,否则不能正常使用。

目前为止JDK自带的原生注解有6个:@Retention , @Target , @Inherited , @Documented , @Repeatable , @Native

其中,@Native、@Repeabable是在JDK1.8之后推出的元注解!

注解1 @Retention

@Retention表示注解保留周期,用于提示注解被保留多长时间,

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Retention {

/**

* Returns the retention policy.

* @return the retention policy

*/

RetentionPolicy value();

}

有三种取值:

RetentionPolicy.SOURCE:保留在源码级别,被编译器抛弃(常见的@Override注解就是此类);

RetentionPolicy.CLASS:被编译器保留在编译后的类文件级别,但是被虚拟机丢弃;

RetentionPolicy.RUNTIME:保留至运行时,可以被反射读取。

public enum RetentionPolicy {

/**

* Annotations are to be discarded by the compiler.

*/

SOURCE,

/**

* Annotations are to be recorded in the class file by the compiler

* but need not be retained by the VM at run time. This is the default

* behavior.

*/

CLASS,

/**

* Annotations are to be recorded in the class file by the compiler and

* retained by the VM at run time, so they may be read reflectively.

*

* @see java.lang.reflect.AnnotatedElement

*/

RUNTIME

}

注解2 @Target

@Target: 表示注解可以使用在什么地方

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Target {

/**

* Returns an array of the kinds of elements an annotation type

* can be applied to.

* @return an array of the kinds of elements an annotation type

* can be applied to

*/

ElementType[] value();

}

常见的取值有:

ElementType.TYPE : 表示该注解可以被使用在 【类, 接口,注解,enum】上面

ElementType.FIELD : 表示该注解可以被使用在 【属性域】上面

ElementType.METHOD : 表示该注解可以被使用在 【方法】上面

ElementType.PARAMETER : 表示该注解可以被使用在 【参数】上面

ElementType.CONSTRUCTOR : 表示该注解可以被使用在 【构造函数】上面

E lementType.LOCAL_VARIABLE* : 表示该注解可以被使用在 【局部变量】上面

ElementType.ANNOTATION_TYPE : 表示该注解可以被使用在 【 注解类型】上面

ElementType.PACKAGE : 表示该注解可以被使用在 【包】上面

ElementType.TYPE_PARAMETER : 表示该注解可以被使用在 【输入参数】上面

ElementType.TYPE_USE :

public enum ElementType {

/** Class, interface (including annotation type), or enum declaration */

TYPE,

/** Field declaration (includes enum constants) */

FIELD,

/** Method declaration */

METHOD,

/** Formal parameter declaration */

PARAMETER,

/** Constructor declaration */

CONSTRUCTOR,

/** Local variable declaration */

LOCAL_VARIABLE,

/** Annotation type declaration */

ANNOTATION_TYPE,

/** Package declaration */

PACKAGE,

/**

* Type parameter declaration

*

* @since 1.8

*/

TYPE_PARAMETER,

/**

* Use of a type

*

* @since 1.8

*/

TYPE_USE

}

注解3 @Documented

注解写入文档 表示注解是否能被 javadoc 处理并保留在文档中。

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Documented {

}

注解4 @Inherited

子类继承父类的注解(子类没有任何注解修饰)

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Inherited {

}

注解5 @Repeatable

@Repeatable : 表示注解的属性可以重复!同一种注解多次使用。可以用来表示某个对象存在多个身份。@Repeatable通俗来讲,就是注解容器!

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Repeatable {

/**

* Indicates the containing annotation type for the

* repeatable annotation type.

* @return the containing annotation type

*/

Class extends Annotation> value();

}

JDK提供的其他注解

@Deprecated:用于标志过时的类、方法和成员变量

@Override:用于修饰重写的方法

@SuppressWarnings:用于忽略@Deprecated标志过的警告

@SafeVarargs:参数安全类型注解,用于提示用户参数安全(JDK1.7)

@FunctionalInterface:函数式接口注解,用于定义函数式接口(JDK1.8)

范例

@Override的作用是,提示编译器,使用了@Override注解的方法必须override父类或者java.lang.Object中的一个同名方法。

表示 @Override 只能使用在方法上,保留在源码级别,被编译器处理,然后抛弃掉。

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public @interface Override {

}

二 Spring中的注解

注解1 @Autowired

Spring开发者对@Autowired注解必定是非常了解,其实就是 autowire=byType 就是根据类型的自动注入依赖(基于注解的依赖注入),可以被使用再属性域,方法,构造函数上。

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Autowired {

boolean required() default true;

}

注解2 @Qualifier

@Qualifier 就是 autowire=byName, 当@Autowired注解判断多个bean类型相同时,就需要使用 @Qualifier("xxBean") 来指定依赖的bean的id:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Qualifier {

String value() default "";

}

注解3 @Resource

@Resource 属于JSR250标准,它并不是Spring提供的注解,但是Spring对它提供了支持。

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入。

@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

用于属性域和方法上。使用方式:@Resource(name="xxBean"). 不带参数的 @Resource默认值类名首字母小写。

@Target({TYPE, FIELD, METHOD})

@Retention(RUNTIME)

public @interface Resource {

String name() default "";

String lookup() default "";

Class> type() default java.lang.Object.class;

enum AuthenticationType {

CONTAINER,

APPLICATION

}

AuthenticationType authenticationType() default AuthenticationType.CONTAINER;

boolean shareable() default true;

}

@Resource装配顺序:

如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

注解4 @Component @Repository, @Service, @Controller

@Component 是spring注解,注解后可以被spring框架所扫描并注入到spring容器来进行管理

@Controller, @Service, @Repository, 这几个注解不同于上面的注解,上面的注解都是将被依赖的bean注入进入,而这几个注解的作用都是生产bean, 这些注解都是注解在类上,将类注解成spring的bean工厂中一个一个的bean。@Controller, @Service, @Repository基本就是语义更加细化的@Component。

@Component 是通用注解,其他三个注解是这个注解的拓展,并且具有了特定的功能

@Repository 注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能。注解类作为DAO对象(数据访问对象,Data Access Objects),这些类可以直接对数据库进行操作 有这些分层操作的话,代码之间就实现了松耦合,代码之间的调用也清晰明朗,便于项目的管理;

@Controller 层是spring-mvc的注解,bean会被spring-mvc框架所使用。具有将请求进行转发,重定向的功能。不能被其他注解所互换的。@Controller注解类进行前端请求的处理,转发,重定向。包括调用Service层的方法 @Service注解类处理业务逻辑。

@Service 层是业务逻辑层注解,这个注解只是标注该类处于业务逻辑层。

用这些注解对应用进行分层之后,就能将请求处理,义务逻辑处理,数据库操作处理分离出来,为代码解耦,也方便了以后项目的维护和开发.

注解5 # @RequestParam @RequestBody @PathVariable

用于参数绑定的注解

@PathVariable : 处理requet uri 部分(这里指uri template中variable,不含queryString部分)。当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

@RequestHeader、@CookieValue : @RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。

范例

@RestController

@RequestMapping("/head")

public class DemoController {

@RequestMapping("/info")

public String headInfo(@RequestHeader("Accept-Encoding") String encoding ,@RequestHeader("Keep-Alive")long keepAlive) {

return encoding + " : " + keepAlive;

}

}

@RequestParam

常用来处理简单类型的绑定,通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String--> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;

用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;

该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;

@RequestBody

该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;

它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。

注解6 @PostConstruct 和 @PreDestroy

@PostConstruct 和 @PreDestroy 不是用于依赖注入,而是bean 的生命周期。类似于 init-method(InitializeingBean) destory-method(DisposableBean).

Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 /销毁之前的操作方法,也可以通过 元素的 init-method/destroy-method 属性指定初始化之后 /销毁之前调用的操作方法

容器初始化 bean 和销毁前所做的操作定义方式有三种:

第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化后和销毁bean之前进行的操作

第二种是:通过 在xml中定义init-method 和 destory-method方法

第三种是: 通过bean实现InitializingBean和 DisposableBean接口

范例

public class Boss {

@Resource

private Car car;

@Resource(name = "office")

private Office office;

@PostConstruct

public void postConstruct1(){

System.out.println("postConstruct1");

}

@PreDestroy

public void preDestroy1(){

System.out.println("preDestroy1");

}

}

public class AnnoIoCTest {

public static void main(String[] args) {

String[] locations = {"beans.xml"};

ClassPathXmlApplicationContext ctx =

new ClassPathXmlApplicationContext(locations);

Boss boss = (Boss) ctx.getBean("boss");

System.out.println(boss);

ctx.destroy();// 关闭 Spring 容器,以触发 Bean 销毁方法的执行

}

}

最后说明下Spring对注解的处理

三 spring中注解的处理

spring中注解的处理基本都是通过实现接口 BeanPostProcessor 来进行的:

public interface BeanPostProcessor {

@Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

@Nullable

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

}

相关的处理类有:

AutowiredAnnotationBeanPostProcessor,

CommonAnnotationBeanPostProcessor,

PersistenceAnnotationBeanPostProcessor,

RequiredAnnotationBeanPostProcessor

...

这些处理类,可以通过 context:annotation-config/ 配置隐式的配置进spring容器。这些都是依赖注入的处理,还有生产bean的注解(@Component, @Controller, @Service, @Repository)的处理:

这些都是通过指定扫描的基包路径来进行的,将他们扫描进spring的bean容器。

注意context:component-scan也会默认将 AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor 配置进来。所以context:annotation-config/是可以省略的。另外context:component-scan也可以扫描@Aspect风格的AOP注解,但是需要在配置文件中加入 aop:aspectj-autoproxy/ 进行配合。

你可能感兴趣的:(java,jdk自带注解)