java基础之注解反射静态代理和动态代理

本文探讨了Java中的注解、反射及其在实际应用中的使用,包括元注解、注解保留策略和反射在findViewById中的角色。此外,还详细介绍了静态代理和动态代理的实现步骤,以及如何结合注解、反射来实现OnClick注入。
摘要由CSDN通过智能技术生成

注解(annotation)

元注解: 注解上的注解

注解使用场景:

retention设置不同保留时间级别:

SOURCE:源码级别,语法检查,APT,常见框架

CLASS: 字节码,AOP

RUNTIME: 和反射结合

反射(reflect)

使用注解和反射实现findViewById

1.  创建注解:

// 设置作用域为变量
@Target(ElementType.FIELD)
// 设置保留级别为运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface GetView {
    // 默认value(),如果有其他变量设置,比如id,则在使用的时候要用@GetView(id = "xxx")
    int value();
}

2. 反射得到view并设置给对象变量

public static void getViewById(Activity activity) {
        Class<? extends Activity> obj = activity.getClass();
        Field[] fields = obj.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].isAnnotationPresent(GetView.class)) {
                GetView annotation = fields[i].getAnnotation(GetView.class);
                fields[i].setAccessible(true);
                try {
                    // set第一个参数为变量所属的对象,如果是静态变量,则传null
                    fields[i].set(activity, activity.findViewById(annotation.value()));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

3. 在activity中使用

@GetView(R.id.tv_go_flutter)
TextView tvFlutter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    UIUtils.getViewById(this);
}

反射中获取属性和方法加declared表明获取类内部的,不加declared表明获取类和父类的属性和方法

静态代理的步骤:

1. 创建代理类和被代理类公共的接口类

2. 被代理类实现该接口

3. 代理类实现该接口,并将代理类传入,代理类持有被代理类

 

动态代理创建步骤:

前两步同动态代理

创建Dynamic类实现invocationHandler接口,实现invoke方法,通过构造方法传入Object持有被代理类

通过代理生成代理接口对象,调用接口中的方法

    public static void main(String[] args) {
        Buyer buyer = new Buyer();
        DynamicProxy dynamicProxy = new DynamicProxy(buyer);

        ClassLoader classLoader = buyer.getClass().getClassLoader();
        IHouse agency = (IHouse) Proxy.newProxyInstance(classLoader, new Class[]{IHouse.class}, dynamicProxy);

        agency.buyHouse();
        agency.renderHouse();
    }

使用注解、反射和代理实现OnClick注入

Activity中使用:

@ClickView(R.id.tv_go_flutter)
public void clickGoFlutter(View view) {
    Toast.makeText(MainActivity.this, "跳转flutter", Toast.LENGTH_SHORT).show();
}

首先定义注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClickView {
    int[] value();
}

实现:

public static void injectClick(final Activity activity) {
    Class<? extends Activity> obj = activity.getClass();
    Method[] methods = obj.getDeclaredMethods();
    for (final Method method : methods) {
        if (method.isAnnotationPresent(ClickView.class)) {
            ClickView annotation = method.getAnnotation(ClickView.class);

            Object clickProxy = Proxy.newProxyInstance(View.OnClickListener.class.getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method1, Object[] args) throws Throwable {
                    // 执行View.OnClickListener的onClick方法时转成使用注解标记的方法
                    return method.invoke(activity, args);
                }
            });
            int[] ids = annotation.value();
            for (int id : ids) {
                View view = activity.findViewById(id);
                Method clickListener;
                try {
                    clickListener = view.getClass().getMethod("setOnClickListener", View.OnClickListener.class);
                    // 执行View的setOnclickListener方法,参数为代理生成的View.OnClickListener对象
                    clickListener.invoke(view, clickProxy);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值