• 《Spring》(十六)---- 基于Schema的AOP


    要使用基于Schema的AOP,IoC容器的配置文件应该使用基于Schema的XML,同时在文件投中增加针对AOP的命名空间声明,如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                  http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
        
        <!--相关bean定义-->
    </bean>

    新的基于Schema的AOP配置方式,针对Pointcut,Advisor以及Aspect等概念提供了独立的配置元素。所有这些配置元素都包含在统一的配置元素中,即<aop:config>, <aop:config> 只有一个属性proxy-target-class, 对应ProxyConfig中的proxyTargetClass属性,通过该属性可以控制使用基于类还是基于接口的动态代理。如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                  http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
        
        <aop:config proxy-target-class="true">
            <!--其他aop概念元素定义-->
        </aop:config>    
        
        
    </beans>

      <aop:config>内部可以有三个子元素,分别是<aop:pointcut>,<aop:advisor>和<aop:aspect>。它们三个必须按照顺序进行配置,代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                  http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
        
        <aop:config proxy-target-class="false">
            <aop:pointcut/>
                    <aop:advisor/>
                    <aop:aspect></aop:aspect>
        </aop:config>    
        
        
    </beans>

      另外,可以在同一个配置文件中配置多个<aop:config>.

      <aop:config> 会根据元素内部对应的Pointcut,Advisor以及Aspect的子元素取得必要的织入信息,然后为容器内注册的bean进行自动代理。和使用AutoProxyCreator一样。但两者最好不要混用。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                                  http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
        
        <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods"> // 1
                <aop:before method="preGreeting" pointcut="target(com.ivy.NaiveWaiter) and execution(* greetTo(..))"/> // 2
            </aop:aspect>
        </aop:config>    
        
        <bean id="adviceMethods" class="com.ivy.schema.AdviceMethods"/> // 3
        <bean id="naiveWaiter" class="com.ivy.NaiveWaiter"/>
        <bean id="naughtWaiter" class="com.ivy.NaughtyWaiter"/>
    </beans>

      

      使用一个<aop:aspect>元素标签定义切面,其内部可以定义多个增强。在<aop:config>元素中可以定义多个切面。在1处,切面引用了adviceMethods Bean, 该Bean是增强方法所在的类。通过<aop:before> 声明了一个前置增强,并通过pointcut属性定义切点表达式,method属性指定增强的方法,该方法应该是adviceMethods bean中的方法。

      <aop:config>拥有一个proxy-target-class属性,当设置为true时,表示其中声明的切面均使用CGLib动态代理技术;当设置为false时,使用JDK动态代理。一个配置文件可以同时定义多个<aop:config>,不同的<aop:config>可以采取不同的代理技术。

       

      1, 基于Schema的Aspect声明

    <aop:config>
        <aop:aspect id="myAspect" ref="schemaBasedAspect" order="2">
             ...
        </aop:aspect>
    </aop:config>

      2, 基于Schema的Pointcut声明

      基于Schema的Pointcut声明(<aop:pointcut〉)可以位于两个位置:一个位置是直接声明到<aop:config>下面,这样的Pointcut定义可以在其余的Advisor定义和Aspect定义中共享引用,另一个位置就是<aop:aspect>元素内部,这种Pointcut只能在其所声明的<aop:aspect〉内部引用,相当于修饰符是private。

    <aop:config>
        <aop:aspect id="myAspect" ref="schemaBasedAspect" order="2">
             <aop:pointcut id="privatePointcut" expression="execution(public void *.doSth())" />
             ...
        </aop:aspect>
    </aop:config>
    <bean id="shemaBasedAspect" class="...SchemaBasedAspect"></bean>

      3, 基于Schema的Advice声明

      在基于Schema的AOP中的Advice声明也分为两部分,Advice定义和Advice到容器中的配置。

      

    配置命名切点

      上例2处通过pointcut属性声明的切点是匿名切点,它不能被其他增强或其他切面使用,Spring提供了命名切点的配置方式:

    <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods">
              <aop:pointcut expression="target(com.ivy.NaiveWaiter)" id="greetToPointcut"/>
                <aop:before method="preGreeting" pointcut-ref="greetToPointcut"/>
            </aop:aspect>
        </aop:config>    

      <aop:pointcut>如果位于<aop:aspect>元素中,则命名切点只能被当前<aop:aspect>内定义的元素访问到,为了能被整个<aop:config>元素中定义的所有增强访问,则必须在<aop:config>下定义切点,且必须保证<aop:pointcut>在<aop:aspect>之前定义:

    <aop:config proxy-target-class="true">
            <aop:pointcut expression="target(com.ivy.NaiveWaiter)" id="greetToPointcut"/>
            <aop:aspect ref="adviceMethods">
                <aop:before method="preGreeting" pointcut-ref="greetToPointcut"/>
            </aop:aspect>
            
            <aop:aspect ref="adviceMethods">
                <aop:after method="preGreeting" pointcut-ref="greetToPointcut"/>
            </aop:aspect>
        </aop:config>    

      各类增强配置

    1. 后置增强
        <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods">
                <aop:after-returning method="afterReturning" pointcut="target(com.ivy.Seller)" returning="retVal"/>
            </aop:aspect>
        </aop:config>    

    增强对应方法:

    public void afterReturning(int retVal) {
            // 增强方法,retVal和配置文件中的returning属性值相同
        }

    如果增强不希望接收返回值,就把returning属性和增强方法的对应入参去掉即可。

      2. 环绕增强

    <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods">
                <aop:around method="aroundMethod" pointcut="execution(* serveTo(..) and within(com.ivy.Waiter))"/>
            </aop:aspect>
        </aop:config>

      3. 抛出异常增强

    <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods">
                <aop:after-throwing method="afterThrowingMethod" pointcut="target(com.ivy.Seller) and execution(* checkBill(..))" throwing="iae"/>
            </aop:aspect>
        </aop:config>
    public void afterThrowingMethod(IllegalArgumentException iae) {
            
        }

      4. Final增强

    <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods">
                <aop:after method="afterMethod" pointcut="execution(* com..*.Waiter.greetTo(..))"/>
            </aop:aspect>
        </aop:config>

      5. 引介增强

        <aop:config proxy-target-class="true">
            <aop:aspect ref="adviceMethods">
                <aop:declare-parents types-matching="com.ivy.Waiter+" implement-interface="com.ivy.Seller" default-impl="com.ivy.SmartSeller"/>
            </aop:aspect>
        </aop:config>

      <aop:declare-parents>通过implement-interfaces属性声明要实现的接口,通过default-impl属性指定默认的接口实现,然后通过type-matching属性以切点表达式语法指定哪些bean需要引介Seller接口的实现。

      

  • 相关阅读:
    web service
    常用的正则表达式
    xml
    sql helper
    sql server 表连接
    asp.net页面生命周期
    创建简单的ajax对象
    checkbox选中问题
    ES6之扩展运算符 三个点(...)
    Object.assign()的用法 -- 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象
  • 原文地址:https://www.cnblogs.com/IvySue/p/6589140.html
Copyright © 2020-2023  润新知