IOC

2020-03-27  本文已影响0人  ArcherZang

原文链接:https://blog.csdn.net/cuterabbitbaby/article/details/80559989

  1. IoC 是编程原则 - 不是特定的产品, 不是具体实现方式, 当然也和具体编程语言无关

  2. 在传统编程范式中, 程序调用可重用的库

  3. 在 IoC 原则下, 程序接受通用框架的调用控制 - 框架调用程序代码

  4. 与 IoC 原则相关的概念包括:

  5. IoC 的设计目的包括:

    • 将执行任务和任务实现解耦

    • 让模块专注于设计任务

    • 模块仅依赖于设计契约而无需关注其他系统如何工作

    • 避免模块替换时的副作用

IOC和APO区别

简单来讲两者一个是思想一个是原则,我们运用AOP思想抽离东西之后,又运用IOC原则添加其复用性,减少过度依赖。

AspectJ

IOC5.png

使用场景基于AOP的动态权限管理、基于AOP的业务数据埋点、基于AOP的性能监测系统等等。

配置中Gradle说明:https://www.jianshu.com/p/c66f4e3113b3

使用说明:https://blog.csdn.net/innost/article/details/49387395

术语
IOC1.png
Join Points 说明 示例
method call 函数调用 比如调用Log.e(),这是一处JPoint
method execution 函数执行 比如Log.e()的执行内部,是一处JPoint。注意它和method call的区别。method call是调用某个函数的地方。而execution是某个函数执行的内部。
constructor call 构造函数调用 和method call类似
constructor execution 构造函数执行 和method execution类似
field get 获取某个变量 比如读取DemoActivity.debug成员
field set 设置某个变量 比如设置DemoActivity.debug成员
pre-initialization Object在构造函数中做得一些工作。 很少使用
initialization Object 在构造函数中做得工作 很少使用
static initialization 类初始化 比如类的static{}
handler 异常处理 比如try catch(xxx)中,对应catch内的执行 advice execution 这个是AspectJ的内容,稍后再说
advice execution 这个是AspectJ的内容,稍后再说
Advice分类(通知类型)
切入点指示符

切入点表达式可以通过&&、||和!进行组合,也可以通过名字引用切入点表达式
通过组合,可以建立更加复杂的切入点表达式
1. 选择特定类型的连接点,如:execution,get,set,call,handler

ioc3.png

2:确定连接点的范围,如:within,withincode

关键词 说明 示例
within(TypePattern) TypePattern标示package或者类。TypePatter可以使用通配符 表示某个Package或者类中的所有JPoint。比如within(Test):Test类中(包括内部类)所有JPoint。
withincode(Constructor Signature| Method Signature) 表示某个构造函数或其他函数执行过程中涉及到的JPoint 比如withinCode(* TestDerived.testMethod(..))表示testMethod涉及的JPoint,withinCode( *.Test.new(..))表示Test构造函数涉及的JPoint
cflow(pointcuts) cflow是call flow的意思cflow的条件是一个pointcut 比如cflow(call TestDerived.testMethod):表示调用TestDerived.testMethod函数时所包含的JPoint,包括testMethod的call这个JPoint本身
cflowbelow(pointcuts) cflow是call flow的意思。 比如 cflowblow(call TestDerived.testMethod):表示调用TestDerived.testMethod函数时所包含的JPoint,不包括testMethod的call这个JPoint本身
this(Type) JPoint的this对象是Type类型。(其实就是判断Type是不是某种类型,即是否满足instanceof Type的条件) JPoint是代码段(不论是函数,异常处理,static block),从语法上说,它都属于一个类。如果这个类的类型是Type标示的类型,则和它相关的JPoint将全部被选中。 示例的testMethod是TestDerived类。所以 this(TestDerived)将会选中这个testMethod JPoint
target(Type) JPoint的target对象是Type类型 和this相对的是target。不过target一般用在call的情况。call一个函数,这个函数可能定义在其他类。比如testMethod是TestDerived类定义的。那么 target(TestDerived)就会搜索到调用testMethod的地方。但是不包括testMethod的execution JPoint
args(TypeSignature) 用来对JPoint的参数进行条件搜索的 比如args(int,..),表示第一个参数是int,后面参数个数和类型不限的JPoint。
代码

世界上没有凭空调用,不管你是动态代理或者注解或者AspectJ 都是有注入口存在。
APJ还对我们主动调用的方法做增加,并在静态代码块中做了初始化。我们调用这些有标识符的方法,它就会主动调用我们的加了Aspect标识的类中符合逻辑的方法,这样我们就可以抽离出共性逻辑,做一个单独的模块。

另外withincode这个标识符有问题,省略缺少,各种写法都尝试了都不行,偶尔还爆空指针,从1.9降到1.8也不行,不知道网上的人是怎么写出来了的。


IOC4.png
@Aspect
public class BehaviorTraceAspect {
    //定义切面的规则
    //1、就再原来的应用中那些注解的地方放到当前切面进行处理
    @Pointcut("execution(@com.example.apjdemo.annotation.BehaviorTrace *  *(..))"
//            + "&& args() "
//            + "&& args(android.view.View) "
//            + //"&& within(MainActivity)"
            +"&& !withincode(@com.example.apjdemo.annotation.BehaviorTrace void com.example.apjdemo.MainActivity.mAudio())"
            +"")
    public void methodAnnottatedWithBehaviorTrace() {
    }

    @Pointcut("execution(@com.example.apjdemo.annotation.BehaviorTrace *  *(..)) " +
            "&& methodAnnottatedWithBehaviorTrace() " +
            "&& !within(MainActivity)")
    public void all() {
    }

    //2、对进入切面的内容如何处理
    //@Before 在切入点之前运行
//    @After("methodAnnottatedWithBehaviorTrace()")
    //@Around 在切入点前后都运行
    @Around("methodAnnottatedWithBehaviorTrace()||all()")
    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();
        String value = methodSignature.getMethod().getAnnotation(BehaviorTrace.class).value();

        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        SystemClock.sleep(100);
        long duration = System.currentTimeMillis() - begin;
        Log.e("pp", String.format("%s功能:%s类的%s方法执行了,用时%d ms",
                value, className, methodName, duration));
        return result;
    }
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
    String value();
}
@BehaviorTrace("语音消息")
public void mShake(View view) {
    Log.e("mShake","mShake");
}

//语音消息
public void mAudio(View view) {
    Log.e("mAudio","mAudio");
    mShake(view);
    kewudewithin();
}

//视频通话
public void mVideo(View view) {
    Log.e("mVideo","mVideo");
    kewudewithincode();
}

public void kewudewithin(){
    Log.e("kewudewithin","kewudewithin");
    bumingsuoyi();
}

public void kewudewithincode() {
    Log.e("kewudewithincode","kewudewithincode");
    bumingsuoyi();
}
@BehaviorTrace("bumingsuoyi")
public void bumingsuoyi() {
}

当期两个项目对比下gradle配置

动态代理

摘至作者:jxiang112https://www.jianshu.com/p/85d181d7d09a

流程总结:

校验代理类方法调用处理程序h不能为空
动态生成代理类class文件格式字节流
通过loader加载创建代表代理类的class对象
根据代理类的构造器创建代理类,
根据代理类接口先得到代理类的类全限名、方法列表、异常列表通过ProxyClassFactory内部调用了native层方法
返回动态创建生成的代理类

getProxyClass0,内有判断实现的接口数量不能超过65535就是Short类型的最大值

private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

Proxy.newProxyInstance()->getProxyClass0(loader, intfs)
->proxyClassCache.get(loader, interfaces)->WeakCache.get(K key, P parameter)
对象初始化时就会有个缓存map    
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
        = new ConcurrentHashMap<>();

WeakCache.get()方法:
    supplier实际就是Factory
    获取当前key对应的cacheKey的缓存supplier的map,如果没有创建map并放入缓存map
    从缓存supplier的map中获取supplier
    factory = null
    while循环 {
         if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
         }
         如果factory = null
           factory = new Factory(key, parameter, subKey, valuesMap);
         如果supplier  = null
           把factory放入cacheKey对应的缓存supplier的map
           supplier =  factory;
     }

Factory.get->value = Objects.requireNonNull(valueFactory.apply(key, parameter))->valueFactory构造方法传入 new ProxyClassFactory()->ProxyClassFactory.apply(ClassLoader loader, Class<?>[] interfaces)
 @FastNative private static native Class<?> generateProxy(
     String name, Class<?>[] interfaces,ClassLoader loader, Method[] methods,                  Class<?>[][] exceptions);
  1. 使用类加载器加载步骤2中的字节流,创建生成动态代理类对象
  2. 使用步骤3中创建生成的代理类对象
使用
IMy iMy = new MyImpl();
MyProxy myProxy = new MyProxy(iMy);
myProxy.ganni();

IMe iMe = new MeImpl();
MeProxy meProxy = new MeProxy(iMe);
meProxy.dani();

DynamicProxy dynamicProxy = new DynamicProxy(meProxy);
IMe iMeProxy = (IMe) Proxy.newProxyInstance(getClassLoader(), new Class[]{IMe.class}, dynamicProxy);
iMeProxy.dani();
DynamicProxy dynamicProxy2 = new DynamicProxy(myProxy);
IMy iMyProxy = (IMy) Proxy.newProxyInstance(getClassLoader(), new Class[]{IMy.class}, dynamicProxy2);
iMyProxy.ganni();

public interface IMe {
    String dani();
}

public interface IMy {
    String ganni();
}

public class MeImpl implements IMe {
    @Override
    public String dani() {
        return null;
    }
}

public class MeProxy implements IMe{

    private final IMe mIme;

    public MeProxy(IMe iMe) {
        mIme = iMe;
    }

    @Override
    public String dani() {
        da110();
        return mIme.dani();
    }

    private void da110(){
        Log.e("MeProxy","woda110");
    }
}

public class MyImpl implements IMy {
    @Override
    public String ganni() {
        return "laiba";
    }
}

public class MyProxy implements IMy {

    private final IMy mIMy;

    public MyProxy(IMy iMy) {
        mIMy = iMy;
    }

    @Override
    public String ganni() {
        da110();
        return mIMy.ganni();
    }

    private void da110(){
        Log.e("MyProxy","woda110");
    }
}

public class DynamicProxy implements InvocationHandler {

    private final Object mobject;

    public DynamicProxy(Object object) {
        mobject = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Log.e("MyProxy",proxy.getClass().getName());
        Log.e("MyProxy",mobject.getClass().getName());

        return method.invoke(mobject,args);
    }

    private void da110(){
        Log.e("MyProxy","wotisuoyouren da110");
    }
}

AutoService

利用@AutoService(IFunction.class)通过ServiceLoader.load(IFunction::class.java)找到所有实现类

有人说可以用来打包https://www.jianshu.com/p/a94e6a32f10f

这里主要介绍@AutoService(Processor.class)就是APT

APT&&Javapoet

中间还加如了javapoet

上一篇下一篇

猜你喜欢

热点阅读