IOC反射注解框架

IOC 反射注解框架

本文地址:https://blog.csdn.net/xiaowu_zhu/article/details/83019525

IOC 反射框架包含了java反射、注解(运行时)、Android相关的控件注入等

Java反射

在Android中反射无处不在,当我们观看Android源码的时候,你就会发现官方用了好多反射,我们反射构造方法、方法、成员变量、静态字段和类型等。

由于篇幅有限,就不详细讲解了,就讲讲我经常用到的吧。

反射会影响性能,请按需使用

注意: 在反射私有的时候,需要设置setAccessible(true),不然会报错

通过反射获取构造方法

  • 带有参数的构造方法

    //开放的构造方法
    public Constructor<T> getConstructor(Class<?>... parameterTypes){}
    //私有的构造方法
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes){}
    
  • 获取所有的构造方法

    //获取所有开放的构造方法
    @CallerSensitive
    public Constructor<?>[] getConstructors() throws SecurityException {}
    //获取私有的构造方法
    public Constructor<?>[] getDeclaredConstructors() throws SecurityException {}
    
    
  • 用法

    • 创建一个对象T实例

      T.class.get...(...) //根据类的实际构造方法、参数来调用
      
    • 如果我们要实例话的类中有无参的构造方法,我们可以通过以下方式创建

      T.class.newInstance() //创建一个对象实例
      

通过反射获取变量

  • 通过字段的名字获取成员变量的Field
//根据name获取公开的成员变量
public Field getField(String name){}
//根据name获取私有的成员变量(是个navtive方法)
public native Field getDeclaredField(String name) throws NoSuchFieldException;
  • 获取某个类中所有的成员变量Field
//获取公有的
@CallerSensitive
public Field[] getFields() throws SecurityException {}
//获取私有的
@FastNative
public native Field[] getDeclaredFields();
  • 通过获取到的Field,调用getand set方法获取值和设置值
//t为某个对象实例
Field field = t.getClass().getField("name");
//通过调用Field中的get方法,获取到相应的值
Object object = field.get(t);
//通过Field中的set方法,设置值
field.set(t, "张三");

//如果field是静态的变量,获取值的时候get参数为null
Object object = field.get(null);

知识点:

基本数据类型的包装类需要获取它们的基本类型时,通过查看源码可用:

  • 如需要通过反射将Integer.class–> int.class时, 其余类似:
Class<?> intClass = Integer.class.getField("TYPE").get(null);

通过反射执行某个方法

  • 通过方法名和参数获取方法

    //获取公开的方法
    @CallerSensitive
    public Method getMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
    }
    //获取私有的方法
    @CallerSensitive
    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
    }
    
  • 获取所有的方法

    //获取有的公开方法
    @CallerSensitive
    public Method[] getMethods() throws SecurityException {
    }
    //获取所有的私有方法
    public Method[] getDeclaredMethods() throws SecurityException {
    }
    
  • 通过获取到的方法反射执行

    //通过方法名获取T对象中公开的setName方法
    Method method =T.class.getMethod("setName");
    //反射执行方法,setName(name), t为T对象的实例,“name”是参数
    method.invoke(t, "name");
    

    以上几种方式都是比较常用的,但是反射不仅仅只是于此,我们还可以用途来获取类,接口,修饰符等等

获取泛型的类型

//获取当前运行类的泛型对象
public static <T> Type analysisClassType(T t) {
    Type type = t.getClass().getGenericSuperclass();
    Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
    return typeArguments[0];
}

使用反射的优化

我们都知道使用反射会影响性能,但是这点性能相对于手机渲染UI等来说,并没有多严重。但是我们也需要做一些优化,来减少影响。

  • 善用API

    尽量直接获取,不要遍历,比如: 尽量使用getMethod("")来获取方法,而少用getMethods()

  • 常用的缓存

    比如,需要多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多:

    // 1. 没有缓存
    void createInstance(String className){ 
        return Class.forName(className).newInstance();
    }
    // 2. 缓存forName的结果
    void createInstance(String className){
        cachedClass = cache.get(className);
        if (cachedClass == null){ 
            cachedClass = Class.forName(className);  
            cache.set(className, cachedClass);  
        }    
        return cachedClass.newInstance();
    }
    

注解

注解可以向编译器、虚拟机等解释说明一些事情。

系统注解

系统提供了很多注解,比如我们常见的@Overried,它作用于某个方法上,表示此方法复写了父类的某个方法。在这里就不一一介绍了。

自定义注解

注解用@interface定义一个注解。下面是一个自定义注解:

@Target(ElementType.TYPE) //注解作用于位置
@Retention(RetentionPolicy.RUNTIME) //注解的生命期
public @interface ContentView {
    @LayoutRes int value() default -1; //可选
}

解释:

  • @Target修饰,表示当前这个注解作用于那种类型,他有如下几种类型:

    public enum ElementType { 
        /** Class, interface (including annotation type), or enum declaration */
        TYPE, //类
        /** Field declaration (includes enum constants) */
        FIELD, //字段
        /** Method declaration */
        METHOD, //方法
        /** Formal parameter declaration */
        PARAMETER, //参数
        /** Constructor declaration */
        CONSTRUCTOR, //构造方法
        /** Local variable declaration */
        LOCAL_VARIABLE, //局部变量
        /** Annotation type declaration */
        ANNOTATION_TYPE,//注解类型
        /** Package declaration */
        PACKAGE, //包上
        /**
         * Type parameter declaration
         * @since 1.8
         */
        TYPE_PARAMETER, //类类型
        /**
         * Use of a type
         * @since 1.8
         */
        TYPE_USE //
    }
    
  • @Retention修饰,表示当前注解的生命周期,可以分为运行时注解编译时注解。

    有如下类型:

    public enum RetentionPolicy {
        /**
         * Annotations are to be discarded by the compiler.
         */
        SOURCE, //作用于源码
        /**
         * Annotations are to be recorded in the class file by the compiler
         * but need not be retained by the VM at run time.  This is the default
         * behavior.
         */
        CLASS, //作用于类,编译时
    
        /**
         * Annotations are to be recorded in the class file by the compiler and
         * retained by the VM at run time, so they may be read reflectively.
         *
         * @see java.lang.reflect.AnnotatedElement
         */
        RUNTIME //运行时
    }
    

自定义注解的处理方式

  • 运行时注解

    运行时注解,表示该注解在程序运行时才会起作用,@Retention(RetentionPolicy.RUNTIME)

    /**
      * 寻找@ContentView()标注的注解
      */
    private static ContentView findContentView(Class<?> clazz) {
        //判断当前的class是不是有contentView标识
        boolean annotationPresent = clazz.isAnnotationPresent(ContentView.class);
        if (annotationPresent) {
            return clazz.getAnnotation(ContentView.class); //有就取出,返回
        }
        findContentView(clazz.getSuperclass());//没有继续查找
        return null;
    }
    
    
  • 编译时注解

    编译时注解是在程序编译时由java提供的AbstractProcessor类,生成一些方法,目前没有手动去写过,

    感兴趣的可以去参考ButterKinfe的开源库。

例子

具体使用的例子,请查看:github–> IOC

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值