Annotation 其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。
JDK自带的三个 Annotation:
@Override:限定重写父类方法, 该注解只能用于方法
@Deprecated:用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings:抑制编译器警告. (比如没加泛型)
自定义 Annotation
自定义注解的目的:原来写在配置文件中的信息,可以通过注解描述 ,定义Annotation 使用@interface 关键字,在myeclipse中可以直接新建。
配置文件的信息,在注解中采用属性描述,例:String name();
带默认值的方式:String name() default “xxx”
注解属性的类型只能是如下类型:String类型、8大基本数据类型、Class类型、枚举类型、注解类型、以上类型的一维数组
特殊属性value:如果注解中有一个名称value的属性,那么使用注解时可以省略value=部分,如@MyAnnotation(“xxx")
例://注解是一种特殊的java类 使用@interface修饰
public @interface MyAnnotation {
// name既是字段又是方法 name()相当于咱们 bean里的getName
public String name()default"xxx";
public int age();
}
元注解(元Annotation)
定义:元注解简单理解为注解的注解,类似于描述一个注解的信息的配置文件
@Retention 指定注解的作用域
RetentionPolicy.SOURCE : 编译器直接丢弃这种策略的注释
RetentionPolicy.CLASS : 编译器将把注解记录在class 文件中. 当运行Java 程序时, JVM 不会保留注解. 这是默认值
RetentionPolicy.RUNTIME :编译器将把注释记录在class 文件中. 当运行Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释
@Target:指定注解用于修饰类的哪个成员.
@Target 包含了一个名为value,类型为ElementType的成员变量。
@Documented: 用于指定被该元Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档.
@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解
例:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
public String value();
public String name();
public String[] preferences();
}
获取注解信息
public static void main(String[] args) throws Exception {
// 获得 Person类上 run方法上的注解
// 反射获得run方法
Class personClass = Person.class;
Method runMethod = personClass.getMethod("run");
// 获得方法的注解对像,这个必须在person类中的注解加上@Retention(RetentionPolicy.RUNTIME),否则就获取不到
MyAnnotation1 myAnnotation1 = runMethod.getAnnotation(MyAnnotation1.class);
// 获得注解对象的属性
String name = myAnnotation1.name();
System.out.println(name);获取的是aaa
}
public class Person {
@MyAnnotation1(value="abc",name="aaa",preferences="sing")
public void run() {
}
}
注:在servlet3.0中大大体现了注解的好处,例如配置servlet或者filter可以直接在其类名上加上注解直接配置,不用在web.xml中配置。
注解的使用,替换配置文件来实现工厂Dao的解耦
相对配置文件来说针对性强,直接在接口的上面写上注解,比配置文件相对灵活,查找方便。
Dao注解
@Retention(RetentionPolicy.RUNTIME) 不能忘写这个,不写编译就擦除了
public @interface DaoAnnotation {
public String bookDaoClass() default "默认的dao";
public String categoryDaoClass() default "默认的dao";
}
BookDao接口中
加上注解给bookDaoClass赋值为实现类的全类名
@DaoAnnotation(bookDaoClass="cn.itcast.mybookstore.dao.impl.BookDaoImpl")
public interface BookDao {
List getAll();
Book find(String id);
boolean save(Book bean);
boolean update(Book bean);
boolean delete(String id);
int getTotalRecord(String sql, Object[] params);
List getPageData(String sql, Object[] params);
}
CategoryDao接口中
加上注解给categoryDaoClass赋值为实现类的全类名
@DaoAnnotation(categoryDaoClass="cn.itcast.mybookstore.dao.impl.CategoryDaoImpl")
public interface CategoryDao {
List getAll();
Category find(String id);
boolean save(Category bean);
boolean update(Category bean);
boolean delete(String id);
}
Factory中
public class DaoFactory {
private String categoryDaoClassname;
private String bookDaoClassname;
private DaoFactory() {
//bookDaoClassname就为BookDao接口上的注解的bookDaoClass属性值
bookDaoClassname = BookDao.class.getAnnotation(DaoAnnotation.class).bookDaoClass();
//categoryDaoClassname就为CategoryDao接口上的注解categoryDaoClass属性值
categoryDaoClassname = CategoryDao.class.getAnnotation(DaoAnnotation.class).categoryDaoClass();
}
private static DaoFactory factory;
public static DaoFactory newDaoFactory() {
if (factory == null)
factory = new DaoFactory();
return factory;
}
public CategoryDao newCategoryDao() {
try {
return (CategoryDao) Class.forName(categoryDaoClassname)
.newInstance();
} catch (Exception e) {
throw new FactoryException(e);
}
}
public BookDao newBookDao() {
try {
return (BookDao) Class.forName(bookDaoClassname)
.newInstance();
} catch (Exception e) {
throw new FactoryException(e);
}
}
}