• 22_AOP_切面——静态切面


    【Spring AOP 如何定位连接点】

    1.增强提供了连接点的方位信息:如织入到方法前面、后面等。

    2.切点描述的是织入到哪些类的哪些方法上。

    【切点】

      Spring通过org.springframework.aop.Pointcut接口描述切点,Pointcut由ClassFilter和MethodMatcher构成,通过ClassFilter定位到某些特定的,通过MethodMatcher定位到某些特定的方法。这样,Pointcut就拥有了描述某些类的某些特定方法的能力。

    可以看到:

      ClassFilter只定义了一个方法matches(Class clazz),其参数代表一个被检测的类,该方法判别被检测的类是否匹配过滤条件。

    Spring提供了两种方法匹配器:静态方法匹配器和动态方法匹配器。

    1.静态方法匹配器

      仅对方法名签名(包括方法名和入参类型及顺序)进行匹配。静态匹配仅判断一次。

    2.动态方法匹配器

      会在运行期间检查方法入参的值。动态匹配因为每次调用方法的入参可能不一样,导致每次调用方法都必须判断,因此动态匹配对性能的影响较大。

      一般情况,动态匹配不常使用。

    方法匹配器的类型由MethodMatcher接口的isRuntime()方法决定,返回false表示是静态方法匹配器,返回true表示是动态方法匹配器。

    【切点类型】

    Spring提供了6种切点:

    1.静态方法切点:org.springframework.aop.support.StaticMethodMatcherPointcut

      StaticMethodMatcherPointcut是静态方法切点的抽象基类,默认情况下匹配所有的类。StaticMethodMatcherPointcut有两个重要的子类:NameMethodMatcherPointcut和AbstractRegexMethodPoint。前者提供简单的字符串匹配方法签名,后者使用正则表达式匹配方法签名。

    2.动态方法切点:org.springframework.aop.support.DynamicMethodMatcherPointcut

      DynamicMethodMatcherPointcut是动态方法切点的抽象基类,默认情况下它匹配所有的类。DynamicMethodMatcherPointcut已过时!!使用DefaultPointcutAdvisor和DynamicMethodPointcut动态方法匹配器代替。

    3.注解切点

    4.表达式切点

    5.流程切点

    6.复合切点

    【切面类型】

    Spring使用org.springframework.aop.Advisor接口表示切面的概念。

    一个切面同时包含横切代码和连接点信息。切面分为三类:一般切面、切点切面、引介切面。

    1.一般切面:Advisor

      它仅包含一个Advice,Advice包含了横切代码和连接点的信息,所以Advice本身就是一个简单的切面,只不过它代表的是所有目标类的所有方法。由于这个横切面过于宽泛,所以一把不会直接使用。

    2.切点切面:PointcutAdvisor

      包含Advice和Pointcut两个类。我们可以通过类、方法名以及方法方位等信息灵活定义切面的连接点,提供更具适用性的切面。

    3.引介切面:IntroductionAdvisor

    引介切面是对应引介增强的特殊的切面,它应用于类层面之上,所以引介切点适用ClassFilter进行定义。

    【静态普通方法名匹配切面 例子】

    【奔驰车类:BenzCar.java】

    package com.Higgin.part4;
    
    public class BenzCar {
        public void driving(){
            System.out.println("奔驰车在行驶...");
        }
    }

    【宝马车类:BMWCar.java】

    package com.Higgin.part4;
    
    public class BMWCar {
        public void driving(){
            System.out.println("宝马车在行驶...");
        }
    }

    【汽车切面类:CarAdvisor.java】

    package com.Higgin.part4;
    
    import java.lang.reflect.Method;
    import org.springframework.aop.ClassFilter;
    import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
    /**
     * 汽车类的切面CarAdvisor类
     * 实现接口:StaticMethodMatcherPointcutAdvisor
     *                     实现StaticMethodMatcherPointcutAdvisor接口唯一需要定义的是matches()方法,
     * 
     */
    public class CarAdvisor extends StaticMethodMatcherPointcutAdvisor{
    
        /**
         * 切点方法 匹配 
         * 匹配规则:方法名为driving
         *                默认情况下,匹配所有的类
         */
        @Override
        public boolean matches(Method method, Class<?> clazz) {
            return "driving".equals(method.getName());
        }
        
        /**
         * 通过覆盖getClassFilter()方法,让它仅匹配BenzCar类及其子类
         */
        public ClassFilter getClassFilter(){
            return new ClassFilter() {
                /**
                 * 切点类 匹配
                 * 匹配规则:为BenzCar类或其子类
                 */
                @Override
                public boolean matches(Class<?> clazz) {
                    return BenzCar.class.isAssignableFrom(clazz);
                }
            };
        }
        
    }

    【driving方法的前置增强类:DrivingBeforeAdvice.java】

    package com.Higgin.part4;
    
    import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;
    
    /**
     * Driving的前置增强类
     */
    public class DrivingBeforeAdvice implements MethodBeforeAdvice{
    
        @Override
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("要增强的是:"+obj.getClass()+"类 ---"+method.getName()+"方法");  //得到切点的信息
            System.out.println("【前置增强】做好行驶前的准备工作...");
        }
    }

    【Spring的xml配置文件:part4.xml】

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:cache="http://www.springframework.org/schema/cache"  
        xsi:schemaLocation="  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context.xsd  
        http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/tx  
        http://www.springframework.org/schema/tx/spring-tx.xsd  
        http://www.springframework.org/schema/jdbc  
        http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd  
        http://www.springframework.org/schema/cache  
        http://www.springframework.org/schema/cache/spring-cache-3.1.xsd  
        http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop.xsd  
        http://www.springframework.org/schema/util  
        http://www.springframework.org/schema/util/spring-util.xsd">
        
        <!-- 要增强的目标对象1 -->
        <bean id="benzTarget" class="com.Higgin.part4.BenzCar"/>
        <!-- 要增强的目标对象2 -->
        <bean id="bmwTarget" class="com.Higgin.part4.BMWCar"/>
    
        <!-- 前置增强 -->
        <bean id="drivingBeforeAdvice" class="com.Higgin.part4.DrivingBeforeAdvice" />
        
        <!-- 切面 -->
        <bean id="carAdvisor" class="com.Higgin.part4.CarAdvisor"
                p:advice-ref="drivingBeforeAdvice"/>
        
        
        <!-- Spring代理工厂的成员变量配置 -->
        <bean id="parent"  abstract="true" 
             class="org.springframework.aop.framework.ProxyFactoryBean"
            p:interceptorNames="carAdvisor"
            p:proxyTargetClass="true"
        />
        
        <!-- Benz代理 -->
        <bean id="benz" parent="parent" p:target-ref="benzTarget" />
        <!-- BMW代理 -->
        <bean id="bmw" parent="parent" p:target-ref="bmwTarget" /> 
    </beans>

    【测试类:TestCarAdvisor.java】

    package com.Higgin.part4.Test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.Higgin.part4.BMWCar;
    import com.Higgin.part4.BenzCar;
    
    public class TestCarAdvisor {
        public static void main(String[] args) {
            ApplicationContext context=new ClassPathXmlApplicationContext("part4.xml");
            
            BenzCar benz= (BenzCar) context.getBean("benz");
            BMWCar bmw=(BMWCar) context.getBean("bmw");
            
            benz.driving();   //奔驰车的driving方法
            System.out.println("===========================");
            bmw.driving();   //宝马车的driving方法
        }
    }

    【运行结果】

    【静态正则表达式方法 匹配切面  例子】

    【奔驰车类 BenzCar.java】

    package com.Higgin.part5;
    
    public class BenzCar {
        public void driving(){
            System.out.println("benz车行驶.....");
        }
        
        public void stop(){
            System.out.println("benz车停止.....");
        }
        
        public void sliding(){
            System.out.println("benz车漂移.....");
        }
    }

    【前置增强类 】

    package com.Higgin.part5;
    
    import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;
    
    /**
     * 汽车类的前置增强类
     */
    public class CarBeforeAdvice implements MethodBeforeAdvice{
    
        @Override
        public void before(Method method, Object[] args, Object obj) throws Throwable {
            System.out.println("要增强的是:"+obj.getClass()+"类 ---"+method.getName()+"方法");  //得到切点的信息
            System.out.println("【前置增强】做好行驶前的准备工作...");
        }
    }

    【Spring的xml匹配 part5.xml】

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:cache="http://www.springframework.org/schema/cache"  
        xsi:schemaLocation="  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context.xsd  
        http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/tx  
        http://www.springframework.org/schema/tx/spring-tx.xsd  
        http://www.springframework.org/schema/jdbc  
        http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd  
        http://www.springframework.org/schema/cache  
        http://www.springframework.org/schema/cache/spring-cache-3.1.xsd  
        http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop.xsd  
        http://www.springframework.org/schema/util  
        http://www.springframework.org/schema/util/spring-util.xsd">
        
        <!-- 要增强的目标对象1 -->
        <bean id="benzTarget" class="com.Higgin.part5.BenzCar"/>
    
        <!-- 前置增强 -->
        <bean id="drivingBeforeAdvice" class="com.Higgin.part5.CarBeforeAdvice" />
        
        <!-- 正则表达式 匹配 -->
        <bean id="regexAdvisor" 
              class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
              p:advice-ref="drivingBeforeAdvice">
            <property name="patterns">
                <list>
                    <value>.*ing.*</value>
                </list>
            </property>
        </bean>
        
        <!-- Spring代理工厂的成员变量配置 -->
        <bean id="benzCar" 
             class="org.springframework.aop.framework.ProxyFactoryBean"
            p:interceptorNames="regexAdvisor"
            p:target-ref="benzTarget"
            p:proxyTargetClass="true"
        />
    </beans>

    【测试类】

    package com.Higgin.part5.Test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.Higgin.part5.BenzCar;
    
    public class TestRegexAdvisor {
        public static void main(String[] args) {
            ApplicationContext context=new ClassPathXmlApplicationContext("part5.xml");
            
            BenzCar benz=(BenzCar) context.getBean("benzCar");
            
            benz.driving();    //匹配.*ing.*
            
            System.out.println("===================================");
            
            benz.sliding();    //匹配.*ing.*
            
            System.out.println("===================================");
            
            benz.stop();       //不匹配
            
        }
    }

    【运行结果】

  • 相关阅读:
    bzoj1662: [Usaco2006 Nov]Round Numbers 圆环数
    畅通工程——D
    Constructing Roads——F
    FatMouse's Speed——J
    Tickets——H
    免费馅饼——G
    Max Sum Plus Plus——A
    Super Jumping! Jumping! Jumping!——E
    Fling——K
    #define is unsafe——I
  • 原文地址:https://www.cnblogs.com/HigginCui/p/6323131.html
Copyright © 2020-2023  润新知