Spring 中对切点、通知、切面的抽象如下
-  切点:接口 Pointcut,典型实现 AspectJExpressionPointcut 
-  通知:典型接口为 MethodInterceptor 代表环绕通知 
-  切面:Advisor,包含一个 Advice 通知,PointcutAdvisor 包含一个 Advice 通知和一个 Pointcut 
 
 
代理相关类图
-  AopProxyFactory 根据 proxyTargetClass 等设置选择 AopProxy 实现 
-  AopProxy 通过 getProxy 创建代理对象 
-  图中 Proxy 都实现了 Advised 接口,能够获得关联的切面集合与目标(其实是从 ProxyFactory 取得) 
-  调用代理方法时,会借助 ProxyFactory 将通知统一转为环绕通知:MethodInterceptor 

演示 - 底层切点、通知、切面
 public static void main(String[] args) {
        /*
            两个切面概念
            aspect =
                通知1(advice) +  切点1(pointcut)
                通知2(advice) +  切点2(pointcut)
                通知3(advice) +  切点3(pointcut)
                ...
            advisor = 更细粒度的切面,包含一个通知和切点
         */
        // 1. 备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");
        // 2. 备好通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before...");
            Object result = invocation.proceed(); // 调用目标
            System.out.println("after...");
            return result;
        };
        // 3. 备好切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
        /*
           4. 创建代理
                a. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现
                b. proxyTargetClass = false,  目标没有实现接口, 用 cglib 实现
                c. proxyTargetClass = true, 总是使用 cglib 实现
         */
        Target2 target = new Target2();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        factory.addAdvisor(advisor);
        factory.setInterfaces(target.getClass().getInterfaces());
        factory.setProxyTargetClass(false);
        Target2 proxy = (Target2) factory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();
    }
    interface I1 {
        void foo();
        void bar();
    }
    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }
        public void bar() {
            System.out.println("target1 bar");
        }
    }
    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }
        public void bar() {
            System.out.println("target2 bar");
        }
    }
}
  学到了什么
                 a. Spring 的代理选择规则
                 b. 底层的切点实现
                 c. 底层的通知实现
                 d. ProxyFactory 是用来创建代理的核心实现, 用 AopProxyFactory 选择具体代理实现
                     - JdkDynamicAopProxy
                     - ObjenesisCglibAopProxy



















