• Spring_8


    Spring学习(23)--- AOP之Introductions应用

     注意:Aspect instantiation models
      ·schema-defined aspects(基于配置)只支持singleton model(单例模式)
    • 简介允许一个切面声明一个实现指定接口的通知对象,并且提供了一个接口实现类来代表这些对象
    • 由<aop:aspect>中的<aop:declare-parents>元素声明该元素用于声明所匹配的类型拥有一个新的parents(因此得名)

    配置:

    <aop:aspect id="usageTrackerAspect" ref="usageTracking">
              <aop:declare-parents types-matching="com.xyz.myapp.service.*+" 
                                     implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
                                     default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
    </aop:aspect>
    public void recordUsage(){
    	usageTracked.incrementUseCount();
    }
    UsageTracked usageTracked = (UsageTracked) context.getBean("myservice");
    

    例子:

    新建接口Fit及实现类FitImpl

    package com.aop.schema;
    
    public interface Fit {
    	void filter();
    }
    
    package com.aop.schema;
    
    public class FitImpl implements Fit {
    
    	@Override
    	public void filter() {
    		System.out.println("FitImpl.filter");
    
    	}
    
    }
    

    切面类(同上节,不做修改了):

    package com.aop.schema.advice;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    /**
    *
    * 切面类
    *
    */
    public class MyAspect {
    
    	public void before(){
    		System.out.println("MyAspect.before");
    	}
    	
    	public void afterreturning(){
    		System.out.println("MyAspect.afterreturning");
    	}
    	
    	public void afterthrowing(){
    		System.out.println("MyAspect.afterthrowing");
    	}
    	
    	public void after(){
    		System.out.println("MyAspect.after");
    	}
    	
    	public void around(ProceedingJoinPoint pjp) {
    		try {
    			System.out.println("MyAspect.around_1");
    			Object obj=pjp.proceed();
    			System.out.println("MyAspect.around_2");
    		} catch (Throwable e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public void around_init(ProceedingJoinPoint pjp,String name,int age) {
    		System.out.println(name+"  "+age);
    		try {
    			System.out.println("MyAspect.around_1");
    			Object obj=pjp.proceed();
    			System.out.println("MyAspect.around_2");
    		} catch (Throwable e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    XML配置:

    <?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"
            xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-4.1.xsd
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
             
         <bean id="myAspect" class="com.aop.schema.advice.MyAspect"></bean>
         <aop:config>
              <aop:aspect id="myAspectAOP" ref="myAspect">
                <!-- com.aop.schema.advice.*+ 指的是advice包下的所有类 -->
                <aop:declare-parents types-matching="com.aop.schema.advice.*+" 
                                     implement-interface="com.aop.schema.Fit"
                                     default-impl="com.aop.schema.FitImpl"/>
              </aop:aspect>
         </aop:config>
     
    </beans>
    

    单元测试:

    package com.aop.schema;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.aop.schema.advice.ApsectBiz;
    
    public class UnitTest {
    
    	@Test
    	public void test(){
    		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-aop.xml");
    		Fit fit = (Fit)context.getBean("myAspect");
    		fit.filter();
    	}
    }
    

    测试结果:

    七月 11, 2015 1:15:13 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Sat Jul 11 13:15:13 CST 2015]; root of context hierarchy
    七月 11, 2015 1:15:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
    FitImpl.filter

    PS:说明为指定的类型强制指定了一个父类。

     ===Advisors========================================

    Advisor:

    ·advisor就像一个小的自包含的方面,只有一个advise

    ·切面自身通过一个bean表示,并且必须实现某个advice接口,同时,advisor也可以很好地利用AspectJ的切入点表达式

    ·Spring通过配置文件中<aop:advisor>元素支持advisor实际使用中,大多数情况下它会和transactional(事务) advice配合使用

    · 为了定义一个advisor的优先级以便让advice可以有序,可以使用order属性来定义advisor的顺序

    使用Spring事务控制时经常使用的一种方式

     <aop:config>
        <aop: pointcut id="bussinessService"  "execution(* com.xyz.myapp.service..(..))"/>
    <aop: advisor pointcut-ref ="bussinessService"  advice-ref="tx-advice"/>
    
      </aop:config>
    
    <tx:advice id="tx-advice">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
         </tx:attributes>
    </tx:advice>

     例子:

    配置文件:

    <?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:context="http://www.springframework.org/schema/context"
        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/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <context:component-scan base-package="com.imooc.aop.schema"></context:component-scan>
    
        <aop:config>
            <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">
                <aop:pointcut id="idempotentOperation"
                    expression="execution(* com.imooc.aop.schema.advisors.service.*.*(..)) " />
    <!--                  expression="execution(* com.imooc.aop.schema.service.*.*(..)) and -->
    <!--                                 @annotation(com.imooc.aop.schema.Idempotent)" /> -->
                <aop:around pointcut-ref="idempotentOperation" method="doConcurrentOperation" />
            </aop:aspect>
        </aop:config>
        
        <bean id="concurrentOperationExecutor" class="com.imooc.aop.schema.advisors.ConcurrentOperationExecutor">
            <property name="maxRetries" value="3" />
            <property name="order" value="100" />
        </bean>
    
     </beans>

    切面代码

     1 package com.imooc.aop.schema.advisors;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 import org.springframework.core.Ordered;
     5 import org.springframework.dao.PessimisticLockingFailureException;
     6 
     7 public class ConcurrentOperationExecutor implements Ordered {
     8 
     9     private static final int DEFAULT_MAX_RETRIES = 2;
    10 
    11     private int maxRetries = DEFAULT_MAX_RETRIES;
    12     
    13     private int order = 1;
    14 
    15     public void setMaxRetries(int maxRetries) {
    16         this.maxRetries = maxRetries;
    17     }
    18 
    19     public int getOrder() {
    20         return this.order;
    21     }
    22 
    23     public void setOrder(int order) {
    24         this.order = order;
    25     }
    26 
    27     public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
    28         int numAttempts = 0;
    29         PessimisticLockingFailureException lockFailureException;
    30         do {
    31             numAttempts++;
    32             System.out.println("Try times : " + numAttempts);
    33             try {
    34                 return pjp.proceed();
    35             } catch (PessimisticLockingFailureException ex) {
    36                 lockFailureException = ex;
    37             }
    38         } while (numAttempts <= this.maxRetries);
    39         System.out.println("Try error : " + numAttempts);
    40         throw lockFailureException;
    41     }
    42 }

    代码

    package com.imooc.aop.schema.advisors.service;
    
    import org.springframework.dao.PessimisticLockingFailureException;
    import org.springframework.stereotype.Service;
    
    @Service
    public class InvokeService {
        
        public void invoke() {
            System.out.println("InvokeService ......");
        }
        
        public void invokeException() {
            throw new PessimisticLockingFailureException("");
        }
    
    }

    单元测试:

    package com.imooc.test.aop;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.BlockJUnit4ClassRunner;
    
    import com.imooc.aop.schema.advisors.service.InvokeService;
    import com.imooc.test.base.UnitTestBase;
    
    @RunWith(BlockJUnit4ClassRunner.class)
    public class TestAOPSchemaAdvisors extends UnitTestBase {
        
        public TestAOPSchemaAdvisors() {
            super("classpath:spring-aop-schema-advisors.xml");
        }
        
        @Test
        public void testSave() {
            InvokeService service = super.getBean("invokeService");
            service.invoke();
            
            System.out.println();
            service.invokeException();
         }
    
    }
  • 相关阅读:
    SpringMVC引入CSS等文件
    idea运行时默认显示的index.jsp修改方法
    Spring 中的 JDBCTemplate
    Spring 错误 cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'context:property-placeholder'.
    Spring IOC 三种注入方式(构造器,setter,接口)
    Java中的Object、T(泛型)、?区别
    DBUtils 笔记
    DBCP + C3P0 连接池
    Servlet+JSP 对外访问路径配置
    linux iptables使用
  • 原文地址:https://www.cnblogs.com/charles999/p/6651119.html
Copyright © 2020-2023  润新知