zoukankan      html  css  js  c++  java
  • spring aop

     
    (一) AOP的几种实现机制
     
        1.静态代理
            缺点 :
                不灵活.
                    原因 : 需要其他编译器预编译,再织入到系统中,方可使用.
                    
        
        2.动态代理
            缺点 :
                a.性能 比 静态代理 稍逊. 随着jvm的发展 , 差距越来越小 .
                b.模块类需要实现接口 . 动态代理只对接口有效 .
                
        3.动态字节码增强
            缺点 :
                使用final修饰过的类和方法 是无法动态增强的.
                    原因 : 该方案的思想是 生成目标类的子类,达到将横切逻辑加入其中的新方法覆盖父类的.因此,使用final修饰符的无法达到.
                    
        4.java代码生成
            缺点 : 需要专门的部署接口 / 部署工具 .目前基本退役 .
            
        5.自定义类加载器
            缺点 : 本身这种策略 是很强大的 .
            但是 , 问题出现在类加载器本身 . 很多应用程序都有自己的类加载体系控制整个系统 , 这种情况使用它 ,很可能造成问题.
            
        6.AOL 扩展
            缺点 : 很强大 , 但很难掌握的一种方式. 首先需要学一门拓展了旧有语言的aol语言 , 甚至是新的一门aol语言.
            
            
            
    (二) 一些aop概念(基于AspectJ)
        
        1.Joinpoint :
            解释 :
                    织入操作的系统执行点.
                    
            包含 :
                    方法调用 , 方法调用执行 , 构造方法调用 , 构造方法执行 , 字段设置 , 字段获取 , 异常处理执行 , 类初始化(静态类型/静态块初始化)
        
        2.Pointcut :
            
            解释 :
                    joinpoint的表述形式 . pointcut中包含了joinpoint的相关信息 .    
                    
            包含 :
                    确定的方法名称 , 正则表达式 , 特定的pointcut表述语言 .
                    
            pointcut的运算 : 可以使用 逻辑与 或 逻辑或 (&& , ||) 进行运算 .
            
        3.Advice :
     
            解释 : 代表了 将要织入到joinpoint的横切逻辑 . 注意 代表的是 横切逻辑 , 逻辑 , 辑 ..
            包含 :
                before advice
                
                after advice :
                    after returning advice
                    after throwing advice
                    after (final) advice
                    
                around advice (也称 interceptor , 拦截器)
                
                Introduction :
                    解释 : 与前几种advice 不同 .
                            introduction 不是根据切入时机来区别对待(或说独立出来) , 而是因为它提供的功能与前几个advice不同.
                            introduction 可以为原有的对象添加新的特性或行为.
                        
        4.Aspect :
                
            解释 : aspect 是 对系统中 横切关注点 以及 横切逻辑 进行封装的 aop概念的实体.
                    它可以包含 多个pointcut 以及 相关的advice 定义.
                    
        5.Weaver :
            解释 : 织入器.
                将所有 包含了pointcut,advice的aspect 织入到系统中的工具.
                它可能是 编译器 , 也可以是 自定义类加载器 , 或者 proxyfactory类 etc.
                
        6.TargetObject :
            解释 : 目标对象. 将符合pointcut的条件/规则 的 横切逻辑 以及 横切点 , 在织入过程中 织入到指定的对象.这个对象成为目标对象 .
            
                    
                    
    (三) Spring AOP
        
        1.实现机制 : 采用动态代理 以及 字节码生成技术.
        
            a.动态代理
                代理模式 : (可以让请求转发 , 最重要的是在转发过程中 可以添加 访问限制等功能)
                    代理类 实现 和 目标类相同的 接口 , 并持有改接口的引用 , 代理方法中调用目标类的目标方法(通常是利用接口的引用调用)
                    但是对于 aop来讲 , 当有一个新的接口 , 以及新接口的实现类 中也有要拦截的方法(即joinpoint相同) , 就需要创建一个新的代理类,这样不好不好~
                    
                动态代理模式 :
                    动态代理模式机制的实现 主要由一个类(java.lang.reflect.Proxy) 与 一个接口(java.lang.reflect.InvocationHandler) 组成.
                    具体用法 :
                        ①.代理类 实现InvocationHandler接口 , 进行横切逻辑书写.
                        ②.使用Proxy类创建对应的目标类. 通常要提供一个 loader , interface , impl class
                    
                    Demo :
                            public class RequestCtrlInvocationHandler implements InvocationHandler{
                                    private static final Logger logger = LoggerFactory.getLogger(RequestCtrlInvocationHandler.class);
                                    Object target ;
     
                                    public RequestCtrlInvocationHandler(Object target){
                                            this.target = target ;
                                    }
     
                                    @Override
                                    public Object invoke(Object proxy , Method method , Object[] args) throws Throwable{
                                            if ( "request".equals(method.getMethodName()) ){
                                                    TimeOfDay startTime = new TimeOfDay(0,0,0);
                                                    TimeOfDay endTime = new TimeOfDay(5,59,59);
                                                    TimeOfDay currentTime = new TimeOfDay();
     
                                                    if(currentTime.isAfter(startTime) && currentTime.isBefore(endTime) ){
                                                            logger.warn("between 0:00 AM and 6:00 AM , the service call is not avilibale ~");
                                                            return null ;
                                                    }
                                                    return method.invoke(target , args);
                                            }
                                            return null ;
                                    }
     
     
                                    public static void main(String[] args){
                                            IRequestable requestable = Proxy.newProxyInstance( 
                                                        ProxyRunner.class.getClassLoader() 
                                                        , new Class[]{IRequestable.class} 
                                                        , new RequestCtrlInvocationHandler(new RequestableImpl()) 
                                            );
                                            requestable.request();
     
                                            ISubject subject = Proxy.newProxyInstance(
                                                        ProxyRunner.class.getClassLoader() 
                                                        , new Class[]{ISubject.class} 
                                                        , new RequestCtrlInvocationHandler(new SubjectImpl()) 
                                            );
                                            subject.request();
                                    }
     
                            }
                    
                缺点:
                    动态代理实现的aop , 只能对 实现了某个接口的实现类(目标对象) 进行代理 , 如果该目标类没有实现任何接口 , 就拿爪儿了 ~
                    
            
            b.字节码生成(通常借助CGLIB动态字节码生成库).
                
                a.原理 : 通过字节码动态生成 技术 , 为指定的目标类 生成一个 相应的子类.子类当然可以对父类进行拓展啦.
                b.步骤 : 利用cglib库
                    ①.代理类需要实现 net.sf.cglib.proxy.CallBack 接口 , 或者实现 net.sf.cglib.proxy.MethodInterceptor接口 , 进行横切逻辑书写
                    ②.通过Enhancer类为 目标对象动态生成一个子类.并将代理类的横切逻辑附加到子类中.
                    
                    Demo : 
                        public class RequestCtrlCallback implements MethodInterceptor{
                                private static fianl Logger logger = Logger.getLogger(RequestCtrlCallback.class);
     
                                @Override
                                public Object intercept(Object target , Method method , Object[] args , MethodProxy proxy) throws Throwable{
                                           if ( "request".equals(method.getMethodName()) ){
                                                    TimeOfDay startTime = new TimeOfDay(0,0,0);
                                                    TimeOfDay endTime = new TimeOfDay(5,59,59);
                                                    TimeOfDay currentTime = new TimeOfDay();
     
                                                    if(currentTime.isAfter(startTime) && currentTime.isBefore(endTime) ){
                                                            logger.warn("between 0:00 AM and 6:00 AM , the service call is not avilibale ~");
                                                            return null ;
                                                    }
                                                    return proxy.invokeSuper(target , args);
                                            }
                                            return null ;
                                }
     
     
                                public static void main(String[] args){
                                        Enhancer enhancer = new Enhancer();
                                        enhancer.setSuperClass(IRequestable.class);
                                        enhancer.setCallback( new RequestCtrlCallback() );
     
                                        IRequestable proxy = (IRequestable) enhancer.create();
                                        proxy.request();
                                }
                        }
     
     
     
     
     
    Spring AOP 相关概念
        1.JoinPoint
     
            只支持方法级别的joinpoint , 确切的说 只支持 "方法执行" 类型的joinpoint .
        
        2.PointCut
        
            a.接口定义 :
            
                public interface Pointcut {
                
                    // 匹配将要被执行织入操作的 对象
                    ClassFilter getClassFilter();
                    
                    // 匹配将要被执行织入操作的 方法
                    MethodMatcher getMethodMatcher();
                    
                    // 默认对所有对象 以及对象上的所有支持的 pointcut进行匹配
                    Pointcut TRUE = TrueClassFilter.INSTANCE ;
                    
                }
                
                
                // 对pointcut所处的对象进行 Class级别类型的匹配
                public interface ClassFilter{
                
                    boolean matches(Class clazz);
                    
                    ClassFilter TRUE = TrueClassFilter.INSTANCE;
                }
                
                // 重头戏
                public interface MethodMatcher{
                    
                    // false --> 不考虑目标方法的参数 ; true --> 对目标方法参数进行操作
                    boolean isRuntime();
                    
                    // isRuntime() 返回false时 调用; 称为 "StaticMethodMatcher"
                    boolean matches(Method method , Class targetClass);
                    
                    // isRuntime() 返回true时 调用 ; 称为 "DynamicMethodMatcher"  -- 最好使用static的 避免使用这个的
                    boolean matches(Method method , Class targetClass , Object[] args);
                    
                    MethodMatcher TRUE = TrueMethodMatcher.INSTANCE ;
                
                }
            
            
            b.Spring提供的常见的PointCut
            
                ①.NameMatchMethodPointcut
                    
                    解释 : 其为StaticMethodMatcherPointcut的子类.
                    
                    Demo :
                        NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
                        
                        // 单个方法匹配
                        pointcut.setMappedName("matches");
                        
                        // 或者传入多个 匹配方法名称
                        pointcut.setMappedNames(new String[]{"matches","isRuntime"});
                        
                        // 支持 * 通配符
                        pointcut.setMappedNames(new String[]{"match*","*matches","mat*es"});
                        
                    缺点 : 只能匹配指定的方法名 , 无法匹配方法重载 , 因为没有 函数签名的描述.
                    
                
                ②.JdkRegexpMethodPointcut
                    
                    解释 : 其为StaticMethodMatcherPointcut的子类. 需要 JDK1.4 以上.
                            必须匹配整个方法签名
                    
                    Demo :
                        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
                        
                        // 单个表达式
                        pointcut.setPattern(".*match.*");
                        
                        // 多个表达式
                        pointcut.setPatterns(new String[]{".*match.*",".*matches"});
                    
                    
                
                ③.Perl5RegexpMethodPointcut
                    略过, 都有 JDK 1.4 以上了. 用JdkRegexpMethodPointcut替代.
                
                
                ④.AnnotationMatchingPointcut
                    解释 : JDK5 以上版本可以使用.
                    
                    Demo :
                    
                        @Retention(RetentionPolicy.RUNTIME)
                        @Target(ElementType.TYPE)
                        public @interface ClassLevelAnnotation{
                        }
                
                        
                        @Retention(RetentionPolicy.RUNTIME)
                        @Target(ElementType.METHOD)
                        public @interface MethodLevelAnnotation{
                        }
                
                        @ClassLevelAnnotation
                        public class GenericTargetObject{
                        
                            @MethodLevelAnnotation
                            public void withAnnotation(){
                                System.out.println("i have an apple , i have a pen");
                            }
                            
                            public void noAnnotation(){
                                System.out.println("no apple , no pen !!!-.-");
                            }
                            
                            
                            public static void main(String[] args){
                            
                                // 这两种写法表达的 都是对标注了 @ClassLevelAnnotation 的类中所有的 method进行匹配
                                AnnotationMatchingPointcut clazzLvPc = new AnnotationMatchingPointcut(ClassLevelAnnotation.class);
                                AnnotationMatchingPointcut clazzLvPc1 = AnnotationMatchingPointcut.forClassAnnotation(ClassLevelAnnotation.class);
                                
                                // 对所有 标注了 @MethodLevelAnnotation 的方法进行匹配 , 而不局限于某一个类 , 比如GenericTargetObject
                                AnnotationMatchingPointcut methodLvPc = AnnotationMatchingPointcut.forMethodAnnotation(MethodLevelAnnotation.class);
                                
                                // 对标注了 @ClassLevelAnnotation 的类中 标注了 @MethodLevelAnnotation 的方法 进行匹配. (这里只匹配到 withAnnotation() )
                                AnnotationMatchingPointcut methodLvPc1 = new AnnotationMatchingPointcut(ClassLevelAnnotation.class,MethodLevelAnnotation.class);
                                
                            }
                        
                        }
                        
                
                
                ⑤.ComposablePointcut
                    解释 : 提供 逻辑运算 功能的pointcut类.
                
                
                ⑥.ControlFlowPointcut
                    解释 : 可以帮助你 在调用流程中的 只有指定调用类(special caller)调用了目标类的pointcut才触发织入操作, 忽略其他的调用类
                    
                    用法 :
                        
                        public static void main(String[] args){
                            //指定调用类
                            ControlFlowPointcut pointcut = new ControlFlowPointcut(XxxTargetCaller.class);
                            
                            //指定调用类 , 精确到指定方法
                            ControlFlowPointcut pointcut1 = new ControlFlowPointcut(XxxTargetCaller.class,"xxxMethodName");
                            
                        }
                
                
                
                
        3.Advice
                
            解释: 两种类型 (per-class , per-instance) ,前者实例间共享,后者每个实例有自己的advice.
                  在Spring中 这些 Advice 都是 普通的POJO . 配置上和普通的Bean没有区别.
            
            a.BeforeAdvice
                实现org.springframework.aop.MethodBeforeAdvice接口.
                通常, before advice 不会中断调用流程 , 如果有需要 ,可以用异常来调用.
                
            b.ThrowsAdvice
                实现org.springframework.aop.ThrowsAdvice接口.
                ThrowsAdvice接口没有定义方法 , 但是 子类要遵循以下规则 , []中的参数可以省略.
                    void afterThrowing( [ method , args , target] , ThrowableSubClass);
                    
                Demo :
                    public class ExceptionBarrierThrowsAdvice implements ThrowsAdvice{
                        
                        public void afterThrowing(Throwable t){
                            // 普通异常处理
                        }
                        
                        public void afterThrowing(RuntimeException e){
                            // 运行时异常处理
                        }
                        
                        public void afterThrowing(Method method , Object[] args , Object target , XxxAppException e){
                            // 处理应用程序生成的异常
                        }
                        
                    }
                
                
                
            c.AfterReturningAdvice
                解释 : 只有方法正常返回时才可以执行. 
                            可以访问到方法的返回值 , 但是不可以更改返回值.
                            还可以获得方法,方法参数 以及目标对象的相关信息.
                
            d.AroundAdvice
                解释 :
                    Spring没有提供相应的 after (finally) advice .
                    但是 提供了 AroundAdvice , 它可以做到所有上面提到的advice所能做的.
                    还可以修改返回值.非常强大 , 应用场景最多 .
                    Spring中并没有AroundAdvice接口 , 而是直接使用了 org.aoplliance.intercept.MethodInterceptor 接口.
                    
                Demo :
                
                    public class PerformanceMethodInterceptor implements MethodInterceptor{
                    
                        private static final Logger logger = LoggerFactory.getLogger(this.getClass());
                        
                        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                            StopWatch watch = new StopWatch();
                            try{
                                watch.start();
                                return methodInvocation.proceed();
                            }catch(Exception ex){
                                logger.error("exception happens : " + ex.getCauseMessage());
                            }finally{
                                watch.stop();
                                logger.info(watch.toString());
                            }
                        }
                    
                    }
                    
                
            e.Introduction (Spring中唯一的一个 per-instance类型的Advice)    
                
                //todo 这部分 有点绕 , 麻烦 , 如非真的需要 不用算了 , 毕竟两个实现类的拓展性不好(不知道spring team改了没有) 待补充 ... 2333333
                
                两个具体实现类 :
                
                    ①.DelegatingIntroductionInterceptor
                        该实现类 并不能做到 per-instance , 如果想达到 需要用它的兄弟类,见②.
                        
                    ②.DelegatePerTargetObjectIntroductionInterceptor
                
                
        
           4.Advisor
            解释 :
                Spring提供的 Advisor 对应着 概念中的 Aspect. 可以说Advisor是特殊的/弱化版的 Aspect.
                Advisor 包含 一个Advice 以及一个Pointcut , 而Aspect可以包含 多个Advice 以及多个Pointcut.
                
            两个Advisor家族 :
                
                ①.PointcutAdvisor
                    
                    1).DefaultPointcutAdvisor
                        PointcutAdvisor 门派的大弟子 , 除了IntroductionAdvice , 其他类型的pointcut , advice都可以使用.
                        可以在构造方法,setter中设置pointcut,advice. 实际生产中,推荐使用spring的xml配置,和普通bean的配置没什么不同.
                    
                    2).NameMatchMethodPointcutAdvisor
                        对DefaultPointcutAdvisor的细化:
                            pointcut方面 限制了只可使用NameMatchPointcut,无法更改.
                            advice方面 可以使用除IntroductionAdvice类型以外的advice.
                            
                    3).RegexpMatchPointcutAdvisor
                        限制了只可使用正则表达式进行设置pointcut.
                        除了IntroductionAdvice , 其他类型的advice均可使用.
                        
                    4).DefaultBeanFactoryPointcutAdvisor
                        使用比较少的advisor.
                        通过绑定容器中advice注册的beanName来实例化advice.前提是pointcut匹配成功,否则不实例化.
                        减少了容器启动初期advisor和advice之间的耦合.但会依赖并强行绑定到spring的ioc容器.
                            
                            
                ②.IntroductionAdvisor
                    只能应用于类级别的拦截.
                    只能使用IntroductionInterceptor , 仅限Introduction使用场景.
                    参数有两个 : 一个IntroductionInterceptor的impl类 , 一个接口类型.
                    
                    
            Ordered接口的作用.
                当有多个advisor可以拦截到 同一个方法 , 那么指定他们的拦截顺序有的时候就很有必要,这时可以通过设置order来解决.
                
                
        5.Spring AOP 的织入
            ①.ProxyFactory
                解释 :
                    Spring AOP中 使用org.springframework.aop.framework.ProxyFactory 作为最基本的织入器.
                    AspectJ AOP 使用 ajc编译器 ; JBOSS AOP 使用自定义ClassLoader
                    
                    ProxyFactory 只需要 advisor 和 targetObject 相关信息.
                    对于 非IntroductionInterceptor 类型的advice , ProxyFactory可以内部构造相应的advisor.
                    对于 IntroductionInterceptor 类型 分为两种情况 :
                        如果是DynamicIntroductionAdvice的子类 , 会抛出AopConfigExecption , 因为该子类没有必要的对象目标信息.
                        如果是其他的 , ProxyFactory可以为其配置一个 DefaultIntroductionAdvisor
                    
                Demo :
                    ProxyFactory weaver = new ProxyFactory(XxxTargetObject);
                    Advisor advisor = xxxx;
                    weaver.addAdvisor(advisor);
                    Object proxy = weaver.getProxy();
                    // 可以使用 proxy 做你想做的事儿了~
                    
                    
                使用方式 :
                
                    1).基于接口的代理
                        
                        ProxyFactory weaver = new ProxyFactory(new MockTask());
                        weaver.setInterfaces(new Class[]{ITask.class}); //可以省略 , ProxyFactory会检测到 目标类所实现的接口.
                        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
                        advisor.setMappedName("execute");
                        advisor.setAdvice(XxxAdviceImpl());
                        weaver.addAdvisor(advisor);
                        ITask taskProxy = (ITask) weaver.getProxy();
                        taskProxy.execute();
                        
                        
                    2).基于类的代理 (使用CGLIB)
                    
                        ProxyFactory weaver = new ProxyFactory(new Executable());
                        
                        // 如果目标类(这里是Executable)没有实现任何接口 ,可以省略设置 ,默认使用基于类的代理 ;
                        // 反之,可以强制使用类的代理而非接口代理 : 设置 proxyTargetClass 或者 optimize 为true ,
                        weaver.setProxyTargetClass(true);    
                        
                        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
                        advisor.setMappedName("execute");
                        advisor.setAdvice(XxxAdviceImpl());
                        weaver.addAdvisor(advisor);
                        Executable taskProxy = (Executable) weaver.getProxy();
                        taskProxy.execute();
                    
                    3).对于 Introduction的织入
                        类似对于 基于接口的代理 的织入.
                        不同的是
                            a.必须setInterfaces(xxx);
                            b.可以不用设置advisor , 而是设置advice , ProxyFactory会为Introduction这种使用 DefaultIntroductionAdvisor
            
            
            ②.ProxyFactoryBean
                解释 :
                    另外一个SpringAOP提供的织入器 , 是ProxyFactory的兄弟类 , 同样继承自ProxyCreatorSupport  添加了特有的属性 :
                        proxyInterfaces :
                            与 父容器的interfaces属性一样的功效.
                            
                        interceptorNames :
                            可以 指定多个要织入到目标对象的advice , 拦截器 以及 advisor , 不需要像ProxyFactory那样一个一个指定了.
                        
                        singleton :
                            为true时 , 每次调用getObejct() 返回同一个 proxy实例 ; 反之 , 每次返回不同的实例 .
                            
                使用方式 : (前两者 和 ProxyFactory 并没有什么不同)
                    1).基于接口的代理
                    2).基于类的代理
                    3).对于 Introduction的织入(略)
                    
                    
            ③.AutoProxy
                解释 :
                    SpringAOP提供的自动代理 , 自动化织入方式.
                    需要以ApplicationContext为IoC容器(使用BeanFactory的话,需要进一步编码,否则不是自动化).
                    它的实现是建立在IoC容器的BeanPostProcessor概念上.
                    
                    fake code :
                        
                        for(Bean bean : IocContainer){
                            if(bean.isSatifySomeCondition){ // 关键! 可以通过配置文件 , 或是注解
                                Proxy proxy = createProxyFor(bean); // 无非就是利用 ProxyFactory 或 ProxyFactoryBean 来实现
                            }else{
                                Object object = createInstancce(bean);
                                return object ;
                            }
                        }
                    
                
                具体实现类 :
                    BeanNameAutoProxyCreator    --半自动步枪 , 需要配置自己应该持有那些target 以及相应的 advice
                    DefaultAdvisorAutoProxyCreator    --全自动步枪 , 需要配置 自己 以及 各个单独的 advisor 即可. 可以看出 它只对advisor 有效.
                    
                    
        6.TargetSource            
            解释 :
                spring对target object的封装 , 提供的实现类如下 :
                    1).SingletonTargetSource  -- ProxyFactory 以及 ProxyFactoryBean 都是使用的它 , 每次getTarget(),返回同一个目标类代理的引用.
                    2).PrototypeTargetSource  -- 与 SingletonTargetSource相反 .
                    3).HotSwappableTargetSource
                        比较有用的一个 TargetSource . //todo
                    4).CommonsPoolTargetSource
                    5).ThreadLocalTargetSoure
                    6).自定义TargetSource
                    
                    
                    
                    
                    
    @AspectJ 更多相关话题 :
        1.Advice的执行顺序
            ①.如果这些advice是在同一个 Aspect/Advisor中 , 那么按照定义顺序 排列优先级.
                @Before的 先定义的先执行 ; @AfterReturningAdvice 先定义的最后执行 .
                
            ②.当这些advice是在不同的Aspect中 , 那么就需要借助 Ordered 接口(数值越小 , 优先级越高)
                public class AnotherAspect implements Ordered {
                
                    public int getOrder(){
                        return 100 ;
                    }
                }
                
        2.Aspect的实例化模式
            默认采用的 是singleton模式.
            SpringAOP还支持perthis 以及 pertarget
            
            Demo :
                @Aspect(perthis(execution(boolean *.execute(String,..))))
                public class MultiAdviceAspect{
                    ...
                }
                
            perthis     会为相应的 代理对象 实例化各自的Aspect实例.
            pertarget    为匹配的 单独的目标对象 实例化Aspect实例 .
            
            注意 , 当使用这两种模式的 Aspect , 其Xml中的Bean定义 就不能再使用 scope="singleton" , 否则会报错. 最好连带相应的 目标对象也配置为 prototype类型.
            
            
    基于Schema的AOP :
        即 使用XSD 取代了 DTD . 同一个XML可以配置多个 <aop:config />
        虽然 @AspectJ 模式的AOP支持 三种模式 , 但是 XSD的 只支持 singleton模式.
        当你就喜欢用XML模式配置,或者JVM是5以下的 ,可以使用这种方式来管理AOP , 一般用基于@AspectJ就ok了.
            <!-- 只有proxy-target-class属性 , 默认为 fasle 即基于 接口的代理 todo-->
            <aop:config proxy-target-class="fasle">
                <aop:pointcut />
                <aop:advisor />
                <aop:aspect />
            </aop:config>
            
            <aop:config proxy-target-class="true">
                <aop:pointcut />
                <aop:advisor />
                <aop:aspect />
            </aop:config>
            
            
            Demo :
                <aop:config>
                    <aop:advisor
                        id="performanceAdvisor"
                        pointcut-ref="targetPointcut"
                        advice-ref="targetAdvice"
                        order="1"
                        />
                </aop:config>
                
                <bean id="targetPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" >
                    <property name="pattern" value="..." />
                </bean>
                
                <bean id="performanceInterceptor" class="...PerformanceMethodInterceptor" />
                
                其中,pointcut-ref
                    a.可以用pointcut替代 , 直接指定pointcut="execution(...)"
                    b.可以在 <aop:advisor>中定义 一个或多个 <aop:pointcut> , 然后 在<aop:advisor>甚至<aop:aspect>中 使用pointcut-ref属性来指定.
                        如果<aop:pointcut>中的type="regex" ,那么 可以书写expression="xx正则表达式" .
                        默认type="aspectj" , 采用的是 pointcut 表达式的 处理方案.
                        但是 type只是语义上如此 , 实际情况 是 type="regex"时, 仍然使用的是默认的类型,而不是正则表达式 , 该bug不知道目前是否修复.todo
                        
                    
                        
                
     
  • 相关阅读:
    ASP.NET Aries 高级开发教程:如何写WebAPI接口
    ASP.NET Aries 高级开发教程:行内编辑事件怎么新增数据到后台(番外篇)
    ASP.NET Aries 高级开发教程:表单检测字段是否已存(番外篇)
    Gemini.Workflow 双子工作流正式上线(支持.NET Core)
    Gemini.Workflow 双子工作流入门教程五:业务表单开发
    Gemini.Workflow 双子工作流入门教程四:流程应用
    Gemini.Workflow 双子工作流入门教程三:定义流程:流程节点、迁移条件参数配置
    Gemini.Workflow 双子工作流入门教程二:定义流程:流程节点介绍
    Gemini.Workflow 双子工作流入门教程一:定义流程:流程图属性
    CYQ.Data 支持分布式数据库(主从备)高可用及负载调试
  • 原文地址:https://www.cnblogs.com/lmxxlm-123/p/11131917.html
Copyright © 2011-2022 走看看