美文网首页
了解和使用 IOC 注入

了解和使用 IOC 注入

作者: 奇梦人 | 来源:发表于2019-08-05 00:01 被阅读0次
1. 什么是 DIP 、 IOC 、DI

依赖倒置原则 (DIP)
强调系统的 高层组件 不应当依赖于 底层组件,并且不论是高层组件还是底层组件都应该依赖于抽象。抽象不应当依赖于实现,实现应当依赖于抽象(软件设计原则)

控制反转(IOC )
一种反转流、依赖和接口的方式。就是将控制权 往高处/上层 转移,控制反转是实现依赖倒置的一种方法(DIP的具体实现方式)

依赖注入 DI
组件通过构造函数或者 set 方法,将其依赖暴露给上层,上层要设法取得组件的依赖,并将其传递给组件,依赖注入是实现控制反转的一种手段 (IOC的具体实现方式)

IOC 容器
依赖注入的框架,用来映射依赖,管理对象创建和生存周期

2. IOC 的核心是解耦

解耦的目的是: 修改耦合对象时不影响另外一个对象,降低模块之间的关联
优点:代码量少,加速开发
缺点:产生性能消耗

** 例子
 public void MainActivity extends Activity{
   @Inject UserInfo userInfo;
    // 省略 
 }

反射 (Reflect)

API 描述
getClass() 获取类
getAnnotation(xx.class) 获取注解
getMethod() 获取方法
invoke(xx,yy) 执行方法
getDeclaredMethods() 获取所有方法
getDeclaredFields() 获取所有属性
annotationType() 获取注解的类型

注解

@Target 该注解用在什么上
ElementType.TYPE 类或接口,注解
ElementType.FIELD 属性
ElementType.METHOD 方法
ElementType.PARAMETER 参数
ElementType.CONSTRUCTOR 构造方法
ElementType.LOCAL_VARIABLE 局部的变量
ElementType.ANNOTATION_TYPE 作用于另一个注解之上
ElementType.PACKAGE
@Retention 该注解用在什么上
RetentionPolicy.SOURCE 类或接口,注解
RetentionPolicy.CLASS 编译时编译
RetentionPolicy.RUNTIME 运行时编译
2. 自定义注解

布局注解

* 首先创建一个注解
@Target(ElementType.TYPE) //该注解作用于类之上
@Retention(RetentionPolicy.RUNTIME) // jvm 在运行时通过反射获取注解的值
public @interface setContentView {
    int value();
}


 *然后是实现
private static void injectLaout(Activity activity) {
        //获取类
        Class<? extends Activity> claszz = activity.getClass();
        //获取这个类上的注解
        setContentView annotation = claszz.getAnnotation(setContentView.class);
        if (annotation != null){
            // 获取这个注解的值
            int layoutId = annotation.value();
            //执行方法: setContentView

            //第一种方法
            //activity.setContentView(layoutId)
            //第二种方法
            try {
                Method method = claszz.getMethod("setContentView", int.class);
                //执行方法
                method.invoke(activity,layoutId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

* 使用  ,注意injectLaout 方法要在父类初始化
@setContentView(R.layout.activity_plugin)
public class PluginActivity extends PluginLibActivity {

}

控件注解

//创建注解
@Target(ElementType.FIELD) //该注解作用于s属性上
@Retention(RetentionPolicy.RUNTIME) // jvm 在运行时通过反射获取注解的值
public @interface setContentView {
    int value();
}

//注解实现
private static void injectViews(Activity activity) {
        //获取类
        Class<? extends Activity> clazz = activity.getClass();
        //获取类的所有属性
        Field[] declaredFields = clazz.getDeclaredFields();
        //循环 拿到每个属性
        for (Field field: declaredFields){
            InjectView annotation = field.getAnnotation(InjectView.class);
            if (annotation !=null){
                int viewId = annotation.value();
                //执行方法
                try {
                    Method method = clazz.getMethod("findViewById", int.class);
                    Object view = method.invoke(activity, viewId);
                    //将方法执行返回值view 赋值给全局某属性
                    field.setAccessible(true);// 设置private访问权限
                    field.set(activity,view);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

//使用
InjectView(R.id.btn)
Button btn;
3. 代理原理与用法

代理 (Proxy)
一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象,这样做的好处是:可以在目标对象的基础上,增强额外的功能操作,即扩展目标对象的功能

静态代理 : 从一出生就知道彼此是孪生兄弟
动态代理 : 通过动态去改变他们的关系

4. AOP 原理和拦截

面向切面编程技术,AOP基于IOC基础,是对OOP的有益补充

AOP 将应用系统分为俩部分 : 核心业务逻辑以及横向的通用逻辑
场景: 所有大中型应用都要涉及到的持久化管理(Persistemt)、事务管理(Transaction Management)、安全管理(Security)、日志管理、调试管理等...

单击和长按注解

// 创建
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnClickListener",listenerType = View.OnClickListener.class,callBackListener = "onClick")
public @interface OnClick {
    int[] value();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnLongClickListener",listenerType = View.OnLongClickListener.class,callBackListener = "onLongClick")
public @interface OnLongClick {
    int[] value();
}

//实现
    private static void injectEvents(Activity activity) {
        //获取类
        Class<? extends Activity> clazz = activity.getClass();
        //获取类的所有方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            // 获取每个方法的注解
            Annotation[] annotations = method.getAnnotations();
            //遍历每个方法的注解
            for (Annotation annotation : annotations) {
                //获取注解上的直接类型
                Class<? extends Annotation> type = annotation.annotationType();
                if (type!=null){
                    //通过EventBase  获取3个重要的规律
                    EventBase eventBase = type.getAnnotation(EventBase.class);
                    //事件的3个规律
                    String set = eventBase.listenerSetter();
                    String call = eventBase.callBackListener();
                    Class<?> atype = eventBase.listenerType();


                    //注解的值
                    try {
                        //通过annotationType 获取onClick 注解的value 的值
                        Method method1 = type.getDeclaredMethod("value");
                        int[] viewIds = (int[])method1.invoke(annotation);

                        ListenerInvocationHandler handler = new ListenerInvocationHandler(activity);
                        handler.addMethodMap(call,method);
                        //打包之后,代理处理后续工作
                        Proxy.newProxyInstance(atype.getClassLoader(), new Class[]{atype}, handler);
                        // R.id.xx
                        for (int viewId : viewIds) {
                            //控件的赋值过程
                            View  view = activity.findViewById(viewId);
                            //获取方法
                            Method setter = view.getClass().getMethod(set,atype);
                            //执行
                            setter.invoke(view,viewId);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

// 代理类

public class ListenerInvocationHandler implements InvocationHandler {

    //需要拦截的对象
    private Object target;
    //需要拦截的方法集合
    private HashMap<String,Method> methodHashMap = new HashMap<>();


    public ListenerInvocationHandler(Object target){
        this.target = target;
    }



    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (target!=null){
            //获取需要拦截的方法名
            String methodName = method.getName();//假如是onClick 方法
            // 将拦截的方法 换成了自定义的方法
            method = methodHashMap.get(methodName);//从集合中判断是否需要拦截

            if (method != null){ // 找到了拦截,才执行自定义方法
                if (method.getGenericParameterTypes().length == 0) return method.invoke(target);
                return method.invoke(target,args);
            }
        }
        return null;
    }

    /**
     *  将拦截的方法加入集合
     * @param methodName
     * @param method
     */
    public void addMethodMap(String methodName,Method method){
        methodHashMap.put(methodName,method);
    }
}

//使用
@onClick(R.id.xx,R.id.xx)
public void onClick(){
  
}

相关文章

  • 了解和使用 IOC 注入

    1. 什么是 DIP 、 IOC 、DI 依赖倒置原则 (DIP)强调系统的 高层组件 不应当依赖于 底层组件,并...

  • Spring从入门到放弃 1:IoC

    核心:IoC IoC就是依赖注入,技术原理比较复杂,作为使用者我们可以不了解。IoC实际实现的功能非常直观。 没有...

  • 一、Spring核心机制:依赖注入

    设值注入:IOC容器使用变量的setter方法来注入被依赖的对象。 构造注入:IOC容器使用构造器来注入被依赖的对...

  • 深入理解spring

    一 IOC容器概述 ioc类型:构造注入 属性注入 接口注入 类装载步骤:装载 验证 准备 解析 初始化 使用 卸...

  • Dagger2常用注解诠释

    依赖注入 控制反转(IoC)与依赖注入(DI)浅谈依赖注入理解依赖注入(IOC)和学习Unity Gradle配置...

  • .net 手动实现简易IOC容器

    现在的编程思想,离不开IOC依赖注入,手写实现一个简易IOC容器,更深入理解依赖注入还没了解IOC的可以查阅.ne...

  • 6.Spring IoC练习

    1. 依赖注入和控制反转 依赖注入和控制反转IoC是什么Ioc—InversionofControl,即“控制反转...

  • Java面试题之Spring

    1.依赖注入的方式有哪几种?以及这些方法如何使用? Set注入 构造器注入 接口注入 2.什么是IoC和DI? 依...

  • 手写源码(二):自己实现SpringIOC

    手写IOC IOC控制反转就是通过反射机制帮我们托管了所有的类。我想要自己实现的就是使用XML注入Bean和使用注...

  • 关于依赖注入(typescript)

    一、概念:依赖注入(DI)、控制反转(IOC)、IOC容器 依赖注入(DI)和控制反转(IOC)基本是一个意思,因...

网友评论

      本文标题:了解和使用 IOC 注入

      本文链接:https://www.haomeiwen.com/subject/qntydctx.html