注解
Annotation(注解) 概述:Annotation其实就是代码里的特殊标记,它运用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行, 有了注解技术后,开发人员可以通过注解告诉类如何运行。 三种基本的Annotation: @Override:限定重写父类方法,该注解只能用户方法 @Deprecated:用于表示某个程序元素(类,方法)已过时 @SuppressWarning:压制编译器警告 编写注解: public @interface 注解名{ 属性可以为八大基本数据类型,枚举,注解(可以想成他的孩子,就如XML中还嵌套这其他的元素), Class,以及他们的一维数组,例如: String name();---->这种情况下必须要在使用这个注解的时候写上属性名 细节:value是一个特殊的属性,当只有这一个属性的时候可以不写 String name() default "asd";默认值为“asd”,有了默认值得时候可以不写这个属性,使用默认值 } 元注解:元Annotation只修饰Annotation的Annotation。JDK中定义了如下的元Annotation @Retention:只能用于修饰一个Annotation定义,用于指定该Annotation可以保留的域,@Retention包含一个RetentionPolicy类型的成员变量,通过这个变量指定元 SOURCE->CLASS->RUNTIME(类加载器加载后)(Java程序有这三种状态:) SOURCE:编译器直接丢掉这种策略的注释 CLASS:编译器将注解记录在CLASS文件中,当运行Java程序的时候,JVM不会保留注解,这是默认值 RUNTIME:编译器会把注解记录在CLASS文件中,当运行Java程序时,JVM会保留注解,程序可以用过反射获取注解 @Target:指定注解用户修饰类的哪个成员,@Target包含了一个名为value,类型为ElementType的成员变量(枚举)。 @Documented:用于指定被该元Annotation修饰的Annotation类会被javadoc工具提取成文档。 @Inherited:将它修饰的Annotation会具有继承性,如果某个类使用了被@Inherited修饰的Annotation,则其子类会自动具有该注解 案例:利用注解注入数据源(何如注入对象的问题): @Retention(RetentionPolicy.RUNTIME)//这里一定不能忘记 public @interface Inject { String password() default "123"; String driverClass() default "com.mysql.jdbc.Driver"; String jdbcUrl() default "jdbc:mysql://localhost:3306/bookstore"; String user() default "root"; } 1,注解在方法上: public class BookDao { private ComboPooledDataSource ds; @Inject(driverClass="com.mysql.jdbc.Driver",jdbcUrl="jdbc:mysql://localhost:3306/bookstore",user="root",password="123") public void setDs(ComboPooledDataSource ds) { this.ds = ds; } ------------------------------------------------------------- public class DaoFactory { public static BookDao createBookDao(){ BookDao dao=new BookDao(); //向dao中注入一个连接池 //解析出dao的所有属性 try { BeanInfo info=Introspector.getBeanInfo(dao.getClass(),Object.class); PropertyDescriptor[] pds=info.getPropertyDescriptors(); for(int i=0;pds!=null&&i<pds.length;i++){ //得到bean的每一个属性描述器 PropertyDescriptor p=pds[i]; Method method=p.getWriteMethod();//得到属性的set方法 //看set方法上有没有Inject注解 Inject inject=method.getAnnotation(Inject.class); if(inject==null) continue; Class propertyType=p.getPropertyType(); System.out.println(propertyType); //如有有注解,就用注解配置的信息,创建一个数据库连接池 DataSource ds=createDataSourceByInject(inject,(DataSource) propertyType.newInstance()); method.invoke(dao,ds); break; } } catch (Exception e) { throw new RuntimeException(e); } return dao; } } //用注解的信息,(可能c3p0,也可能是jdcp连接池)为池配属性 private static DataSource createDataSourceByInject(Inject inject,DataSource ds) { //获取到注解所有属性的方法 Method[] method=inject.getClass().getMethods(); for(Method m:method){ String name=m.getName(); System.out.println(name); PropertyDescriptor pd=null; try { pd=new PropertyDescriptor(name,ds.getClass()); Object value=m.invoke(inject,null);//得到注解属性的值 pd.getWriteMethod().invoke(ds,value); } catch (Exception e) { continue; } } return ds; } } 2,注解在变量上:用暴力反射 后边的代码一样: BookDao2 dao=new BookDao2(); Field[] field=dao.getClass().getDeclaredFields(); for(int i=0;field!=null&&i<field.length;i++){ Field f=field[i]; f.setAccessible(true); Inject inject=f.getAnnotation(Inject.class); if(inject==null){ continue; }else{ DataSource datasource=(DataSource) f.getType().newInstance(); DataSource ds=createDataSourceByInject(inject,datasource); f.set(dao,ds); } } return dao;
现在的几乎什么都不懂,但是不代表以后的我也是这样。