`

java 注解Annotation

阅读更多

1.创建一个注解

       创建注解跟接口差不多,不过要在interface前加个@,可以用default在方法后面设置默认值,方法的返回类型包括基本类型、String、Class、enum、Annotation、以上类型数组。还要通过元注解(@Retention、@Target)定义其作用域、有效范围。举一个栗子

	@Retention(RetentionPolicy.RUNTIME)    
	@Target({ElementType.ANNOTATION_TYPE})  
	public  @interface demo{
		public int value();//只有当value()是唯一需要使用时赋值,才可以这样简写@demo(0)
		public String bbb() default "demo";
		public Class<?>  ccc() default Date.class;
		public ElementType ddd() default ElementType.TYPE;
		public Target eee() default @Target(value = { ElementType.TYPE });
		public char[] fff() default {'a','b'};
	}

 

 2.元注解

        元注解专职负责注解其他注解,共四种 @Target、@Retention保留、@Documented(将此注解包含在Javadoc中)、@Inherited(允许子类继承父类),其实元注解跟泛型的通配符(?)差不多概念。先介绍下注解中用到的两个枚举参数

元注解@Target的参数

	public enum ElementType 
	{// 分别表示的作用范围
		TYPE, // 类、接口、注解、泛型
		FIELD, // 域
		METHOD, // 方法
		PARAMETER, // 参数
		CONSTRUCTOR, // 构造方法
		LOCAL_VARIABLE, // 局部变量
		ANNOTATION_TYPE, // 应用于另一个注解上
		PACKAGE; // 包
	  
	  private ElementType() {}
	}

元注解@Retention的参数

	public enum RetentionPolicy
	{
	  SOURCE,  //注解将被编译器丢弃
	  CLASS,   //保存在class文件中,VM 丢弃
	  RUNTIME; //运行时保留,可通过反射获取
	  
	  private RetentionPolicy() {}
	}

 元注解@Target,表示该注解可以用在什么地方

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Target
{
  ElementType[] value();
}

 元注解@Retention,注解的保存级别

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Retention
{
  RetentionPolicy value();
}

 

3. Java内置注解

@Override, 表示当前方法覆盖父类中的方法,如果父类没有该方法,编译器错误

	//源码
	@Target({ElementType.METHOD})
	@Retention(RetentionPolicy.SOURCE)
	public @interface Override {}

 @Deprecated, 用这个标注方法,就会出现一条横线,方法就基本废了

//源码
	@Documented
	@Retention(RetentionPolicy.RUNTIME)
	@Target({ElementType.CONSTRUCTOR, 
			 ElementType.FIELD, 
			 ElementType.LOCAL_VARIABLE, 
			 ElementType.METHOD, 
			 ElementType.PACKAGE, 
			 ElementType.PARAMETER, 
			 ElementType.TYPE})
	public @interface Deprecated {}

  @SuppressWarnings({"all"})  消除警告用

	//源码
	@Target({ElementType.TYPE, 
			 ElementType.FIELD,
			 ElementType.METHOD, 
			 ElementType.PARAMETER, 
		 	 ElementType.CONSTRUCTOR, 
			 ElementType.LOCAL_VARIABLE})
	@Retention(RetentionPolicy.SOURCE)
	public @interface SuppressWarnings {
		String[] value();// 这个数组的参数在下面
	}
关键字 用途
all to suppress all warnings
boxing  to suppress warnings relative to boxing/unboxing operations
cast to suppress warnings relative to cast operations
dep-ann to suppress warnings relative to deprecated annotation
deprecation to suppress warnings relative to deprecation
fallthrough  to suppress warnings relative to missing breaks in switch statements
finally  to suppress warnings relative to finally block that don’t return
hiding to suppress warnings relative to locals that hide variable
incomplete-switch  to suppress warnings relative to missing entries in a switch statement (enum case)
nls  to suppress warnings relative to non-nls string literals
null to suppress warnings relative to null analysis
rawtypes to suppress warnings relative to un-specific types when using generics on class params
restriction to suppress warnings relative to usage of discouraged or forbidden references
serial to suppress warnings relative to missing serialVersionUID field for a serializable class
static-access o suppress warnings relative to incorrect static access
synthetic-access   to suppress warnings relative to unoptimized access from inner classes
unchecked  to suppress warnings relative to unchecked operations
unqualified-field-access to suppress warnings relative to field access unqualified
unused to suppress warnings relative to unused code

 

 下面举一个栗子 

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;

public class AnnotationTest implements InvocationHandler {
	private Object obj;

	public AnnotationTest(Object obj) {
		this.obj = obj;
	}
	
	// ----------------定义注解--------------------
	// 让此枚举保留到运行时
	@Retention(RetentionPolicy.RUNTIME)
	// 用在方法上
	@Target({ ElementType.METHOD })
	public @interface Transaction {
		public boolean value() default true;
	}

	// ---------------定义一个接口------------------
	public interface IDao {
		@Transaction
		// 使用注解
		public void remove();
	}

	// --------------实现接口---------------------
	public static class DaoImpl implements IDao {
		Queue<String> queue;

		public DaoImpl(Queue<String> queue) {
			this.queue = queue;
		}

		@Override
		public void remove() {
			// 删除报错,要求回滚
			if (queue.peek().equals("stop")) {
				throw new NullPointerException();
			}
			System.err.println(queue.poll());
		}
	}

	// --------------得到代理类---------------------
	public Object getProxy() {
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object paramObject, Method paramMethod,
			Object[] paramArrayOfObject) throws Exception {
		// 取方法上面的注解Transaction
		Transaction tran = paramMethod.getAnnotation(Transaction.class);
		boolean isTran = false;
		if (tran != null) {
			isTran = tran.value();// 判断是否需要事务
		}
		Object rtnObj = null;
		try {
			if(isTran){System.err.println("启动事务");}
			rtnObj = paramMethod.invoke(obj, paramArrayOfObject);
			if(isTran){System.err.println("提交事务");}
		}catch(Exception e){
			if(isTran){System.err.println("回滚事务");}
			throw e;
		}
		return rtnObj;
	}

	public static void main(String[] args) {
		Queue<String> queue = new LinkedList<String>();
		Collections.addAll(queue, "1", "stop", "2");

		AnnotationTest test = new AnnotationTest(new DaoImpl(queue));
		IDao dao = (IDao) test.getProxy();
		try {
			while (queue.peek() != null) {
				dao.remove();
			}
		} catch (Exception e) {
			System.out.println("-----------------");
			for (String str : queue) {
				System.out.println(str);
			}
		}
	}
}

 输出:

 

          启动事务
          1
          提交事务
          启动事务
          回滚事务
          -----------------
          stop
          2

 

 

 

spring注解

 

赋值注解和初始化注解是分开的
@Autowired  (赋值注解,默认按照类型匹配)
       

<!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

 

    当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false),这等于告诉 Spring:在找不到匹配 Bean 时也不报错。
    当遇到一个对象不止有一个实例时,按照bean的id进行注解     

 @Autowired
 public void setOffice(@Qualifier("office")Office office) {
     this.office = office;
 }

      
在xml中配置的bean 都可以通过该注解
       可以对私有成员变量进行注解(不需要set方法也可以)
       注解在set方法上
       注解在构造方法
      
      
 @Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,面@Resource 默认按 byName 自动注入罢了@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将@Resource 注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略
 让JSR-250的注释生效

 <bean   class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

  
 JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。

清单 17. 使用 @PostConstruct 和 @PreDestroy 注释的 Boss.java
            

    
package com.baobaotao;

import javax.annotation.Resource;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

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"); 
    }
    …
}

 

您只需要在方法前标注 @PostConstruct 或 @PreDestroy,这些方法就会在 Bean 初始化后或销毁之前被 Spring 容器执行了。
我们知道,不管是通过实现 InitializingBean/DisposableBean 接口,还是通过 <bean> 元素的init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。但是使用 @PostConstruct 和 @PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标注 @PostConstruct 或 @PreDestroy 注释的方法都会在初始化 / 销毁时被执行。

 

 

注解用于初始化

<context:component-scan base-package="com.baobaotao"/>

Spring 2.5 在 @Repository 的基础上增加了功能类似的额外三个注解:
@Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次。
@Service 通常作用在业务层,但是目前该功能与 @Component 相同。
@Constroller 通常作用在控制层,但是目前该功能与 @Component 相同。


@Component 有一个可选的入参,用于指定 Bean 的名称,在 Boss 中,我们就将 Bean 名称定义为“boss”。一般情况下,Bean 都是 singleton 的,需要注入 Bean 的地方仅需要通过 byType 策略就可以自动注入了,所以大可不必指定 Bean 的名称。


@Component 定义的 Bean 都是 singleton 的
----------------每次是一个新实例------------

@Scope("prototype")
@Component("boss")
public class Boss {
    …
}

 Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和@Controller。在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和@Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用@Repository、@Service 和 @Controller 对分层中的类进行注释,而用@Component 对那些比较中立的类进行注释。

  • 注释配置不一定在先天上优于 XML 配置。如果 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注释配置优于 XML 配置;反之如果这种依赖关系会在部署时发生调整,XML 配置显然又优于注释配置,因为注释是对 Java 源代码的调整,您需要重新改写源代码并重新编译才可以实施调整。
  • 如果 Bean 不是自己编写的类(如 JdbcTemplate、SessionFactoryBean 等),注释配置将无法实施,此时 XML 配置是唯一可用的方式。
  • 注释配置往往是类级别的,而 XML 配置则可以表现得更加灵活。比如相比于 @Transaction 事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。
    所以在实现应用中,我们往往需要同时使用注释配置和 XML 配置,对于类级别且不会发生变动的配置可以优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创建和 Bean 注入之前将这两种配置方式的元信息融合在一起。
1
4
分享到:
评论

相关推荐

    Java注解Annotation验证

    Java注解Annotation用起来很方便,也越来越流行,由于其简单、简练且易于使用等特点,很多开发工具都提供了注解功能,不好的地方就是代码入侵比较严重,所以使用的时候要有一定的选择性。 这篇文章将利用注解,来做...

    Java 注解Annotation实例上手文档

    Java注解(Annotation)自JDK 5.0引入以来,已经成为Java语言的重要特性之一,它为代码元数据提供了一种标准化的方式,使得编译器、工具和其他框架能够理解和处理这些元数据。在Java中,注解是一种元数据,可以被...

    java 注解annotation的使用以及反射如何获取注解

    Java注解(Annotation)是Java语言提供的一种元数据机制,用于向编译器或JVM提供额外的信息。这些信息可以用来验证代码、控制代码生成、配置应用等。注解是自Java 5版本引入的特性,它使得程序员可以在源代码中嵌入...

    java注解annotation.rar

    Java注解,也称为 Annotation,是Java编程语言中的一种元数据机制,用于向编译器、JVM(Java虚拟机)或工具提供有关代码的信息。这些信息可以用来进行编译时检查、运行时处理,或者作为配置信息。注解不是程序的一...

    Java 5 annotation 学习笔记

    Java 5引入的注解(Annotation)是一种元数据,它提供了在代码中嵌入信息的方式,这些信息可以被编译器、JVM或其他工具在编译时或运行时使用。注解可以用来简化代码,提高可维护性,并帮助工具进行静态分析。 1. ...

    java1.5 annotation注释源代码

    Java 1.5 引入了一种新的元编程机制——注解(Annotation),极大地增强了代码的可读性和可维护性。注解是一种在代码中添加元数据的方式,它允许程序员在源代码上添加一些信息,这些信息可以被编译器或运行时环境...

    Java自定义注解Annotation的使用

    ### Java自定义注解Annotation的使用 #### 1. 前言 自从JDK 1.5引入了注解这一特性以来,它已经成为Java开发中的一个重要组成部分。注解最初是为了推动EJB 3.0的普及和发展而设计的,其目的是减少配置文件的使用,...

    Java 注解(Annotation)

    Java 注解(Annotation) - 请认准 ih0qtq

    java之Annotation及其应用

    Java注解(Annotation)是Java语言的一个重要特性,它为元数据提供了强大的支持。元数据是一种描述数据的数据,可以提供有关代码的附加信息,而这些信息并不直接影响代码的执行。在Java中,注解用于向编译器、JVM或...

    Java.Annotation注解.part4

    Java.Annotation注解.part4

    Java Annotation注解技术

    Java Annotation注解技术是自Java SE 5.0版本引入的一种元编程机制,它允许程序员在源代码的各个层面(如类、方法、变量等)添加元数据,以供编译器、JVM或第三方工具在编译时或运行时进行处理。Annotation简化了...

    JAVA注解(Annotation).doc

    Java注解,也称为Annotation,是Java编程语言中的一种特性,用于向编译器、JVM或工具提供元数据。元数据是关于数据的数据,它提供了额外的信息,但不直接影响程序的执行。注解在代码中以`@注解名`的形式出现,主要...

    Java Annotation(Java 注解)

    如果你想知道java annotation是什么?你可以看看

    Java注解Annotation解析

    Java注解(Annotation)是Java语言中的一个重要特性,自Java 1.5版本引入以来,它在软件开发中扮演了不可或缺的角色。注解是一种元数据,它可以附加到源代码的不同元素上,如类、方法、变量等,提供了额外的信息,...

    Java.Annotation注解.part3

    Java.Annotation注解.part3

    Java.Annotation注解.part2

    Java.Annotation注解.part2

    Java.Annotation注解.part1

    Java.Annotation注解.part1

    java教程之java注解annotation使用方法

    Java注解(Annotation)是Java语言中的一个重要特性,它允许程序员在源代码中嵌入元数据(metadata),这些元数据不会直接影响程序的执行,但可以被编译器或Java虚拟机(JVM)在编译时或运行时读取,从而实现特定的...

    Java Annotation注解.doc

    在实际开发中,Java注解被广泛用于Spring框架的依赖注入、JPA的实体映射、JSF的UI组件绑定等场景,极大地提高了代码的可维护性和灵活性。然而,对于更复杂的注解使用,如自定义注解生成XML映射文件,需要更深入的...

Global site tag (gtag.js) - Google Analytics