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();
     }

}

 

 

 

posted @ 2017-04-19 17:56  charles999  阅读(185)  评论(0编辑  收藏  举报