注解

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;

 

posted @ 2016-06-12 21:59  戒。  阅读(138)  评论(0编辑  收藏  举报