元注解既是注解在注解方法上的注解,有点绕口,可以简单认为几乎所有注解类会被这5种注解种的N种所修饰
@Target
这是用来标记当前注解的作用范围,java.lang.annotation.ElementType,Target通过ElementType来指定注解可使用范围的枚举集合
取值 |
注解使用范围 |
METHOD |
可用于方法上 |
TYPE |
可用于类或者接口上 |
ANNOTATION_TYPE |
可用于注解类型上(被@interface修饰的类型) |
CONSTRUCTOR |
可用于构造方法上 |
FIELD |
可用于域上 |
LOCAL_VARIABLE |
可用于局部变量上 |
PACKAGE |
用于记录java文件的package信息,这里比较特别 |
PARAMETER |
可用于参数上 |
这里重点说明下:ElementType. PACKAGE。它并不是使用在一般的类中,而是用在固定的文件package-info.java中。这里需要强调命名一定是“package-info”。由于package-info.java并不是一个合法的类,使用eclipse创建类的方式会提示不合法,所以需要以创建文件的方式来创建package-info.java。
例如,定义可使用范围PACKAGE:
@Target({ElementType.PACKAGE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface AsynLog {
}
那么,创建文件:package-info.java,内容如下:
@AsynLog
package org.my.commons.logs.annotation;
@Retention:解释说明注解的存活时间。
它的取值如下:
—— RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
——RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
——RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
@Documented:能够将注解中的元素包含到 Javadoc 中去。
@Inherited:如果一个父类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了父类的注解。
@Repeatable:注解的值可以同时取多个。
·@Service:用于标注业务层组件;
·@Controller:用于标注控制层组件(如Struts中的action);
·@Repository:用于标注数据访问组件,即DAO组件;
·@Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注;
·@Autowired:默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:
@Autowired@Qualifier("personDaoBean")存在多个实例配合使用;
·@Resource:默认按名称装配,当找不到与名称匹配的bean才会按类型装配;
·@PreDestory:摧毁注解,默认单例,启动就加载;
·@Async:异步方法调用;
·@Configuration:把一个类作为一个IOC容器,它的某个方法头上如果注册了@Bean,就会作为这个spring容器中的Bean;
·@Scope:用于指定scope作用域的(用在类上);
·@PostConstruct:用于指定初始化方法(用在方法上);
·@PreDestory:用于指定销毁方法(用在方法上);
·@DependsOn:定义Bean初始化及销毁时的顺序;
·@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常;
·@Lazy(true):表示延迟初始化。
2、@Scope
如上:@Scope可以指定模式,默认还是singleton,即单例模式。“prototype”表示原型,即每次都会new出一个新的出来。
3、@Service
@Service和@Controller、@Repository、@Component其实都是一样的,当你知道这个类具体是干什么的就用具体的注解,如果不知道就用@Component。(概述中已叙述清楚)
另外:这里的@Service,干了两件事:
a.声明该类是一个bean,这样才可以使用@Autowired来自动注入;
b.这个类的bean的id是类名,且首字母小写,你也可以这样做,@Service("这里是你想要的id名")。
4、@Autowired@Qualifier(“指定bean”)配套使用
这种情况是:当出现一个接口有多个实现类时来区分使用,例如下面的AnnotationService,这个接口就有两个实现类。
package com.annotation;
import com.annotation.service.AnnotationService;
@Component
public class QualifierResoutce {
@Autowired
@Qualifier("annotationServiceImpl2")
// @Resource(name="annotationServiceImpl2")
public AnnotationService as;
}
上面的@Component,就是不知道这个类是干嘛的,所以就使用这个注解;
而这两个注解的配套使用就是,自动注入这个属性,并且走的是这个属性(接口)的哪个实现类。
5、@Resource
上面也出现了这个注解,这个注解和@Autowired非常类似。
@Resource的装配顺序:
a.@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配;
b.指定了name或者type则根据指定的类型去匹配bean;
c.指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错。
@Resource和@Autowired的区别:
a.@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配;
b.@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了。
Spring属于第三方的,J2EE是java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。
6、@Controller
@Controller对应表现层的Bean,也就是Action,当使用这个注解以后,spring容器中就会有一个和这个注解的类名相同(首字母小写)的action;
也可以这样@Controller("ActionName")来指定名字;
同样,@Repository,也是这样的。
自定义注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
格式:
@元注解
public @interface 注解名{
String 属性名() default "属性默认值";
}
自定义一个注解:
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AspectAonn {
/**
* 模块
*/
public String title() default "";
}
使用这个注解
@AspectAonn(title="test")
public void dm() {
System.err.println("this service");
}