1. 程式人生 > >Spring--基於AspectJ的AOP開發

Spring--基於AspectJ的AOP開發

例如 dot junit4 dba demo1 out 前置 aspect point

AspectJ簡介

  • ·AspectJ是一個基於Java語言的AOP框架
  • ·Spring2.0以後新增了對AspectJ切點表達式支持
  • ·@AspectJ是AspectJ1.5新增功能,通過JDK5註解技術,允許直接在Bean類中定義切面
  • ·新版本Spring框架,建議使用AspectJ方式來開發AOP
  • ·使用AspectJ需要導入Spring AOP和 Aspect/相關jar包
    • -spring-aop-4.2.4.RELEASE.jar
    • -com.springsource.org.aopalliance-1.0.0.jar
    • -spring-aspects-4.2.4.RELEASE.jar
    • -com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

基於AspectJ的註解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.xsd"> <!-- bean definitions here
--> <!--開啟AspectJ的註解開發,自動代理=====================--> <aop:aspectj-autoproxy/> </beans>

@AspectJ提供不同的通知類型

  • ·@Before 前置通知,相當於BeforeAdvice
  • ·@AfterReturning 後置通知,相當於AfterReturningAdvice
  • ·@Around 環繞通知,相當於MethodInterceptor
  • ·@AfterThrowing異常拋出通知,相當於ThrowAdvice
  • ·@After最終final通知,不管是否異常,該通知都會執行
  • ·@DeclareParents 引介通知,相當於IntroductionInterceptor(不要求掌握)

在通知中通過value屬性定義切點

  • ·通過execution函數,可以定義切點的方法切入
  • ·語法:
    • -execution(<訪問修飾符>?<返回類型><方法名>(<參數>)<異常>)
  • ·例如
    • -匹配所有類public方法 execution(public**(.))
    • -匹配指定包下所有類方法 execution(*com.imooc.dao.*(..))不包含子包
    • -execution(*com.imooc.dao..*(..))..*表示包、子孫包下所有類
    • -匹配指定類所有方法 execution(*com.imooc.service.UserService.*(..))
    • -匹配實現特定接口所有類方法
    • execution(*com.imooc.dao.GenericDAO+.*(..))
    • -匹配所有save開頭的方法 execution(*save*(..))

  案例(前置通知)

  技術分享圖片

    MyAspectAnno

@Aspect
public class MyAspectAnno {
    @Before(value = "execution(* com.windbag.aspectJ.demo1.ProductDao.save(..))")
    public void before(){
        System.out.println("前置通知=====================");
    }

}

    ProductDao

public class ProductDao {

    public void save(){
        System.out.println("保存商品");
    }

    public void update(){
        System.out.println("更改商品");
    }

    public void findone(){
        System.out.println("查詢一個商品");
    }

    public void delete(){
        System.out.println("刪除商品");
    }

    public void findAll(){
        System.out.println("查詢所有商品");
    }
}

    SpringDemo1Test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo1Test {

    @Resource(name="productDao")
    private ProductDao productDao;

    @Test
    public void demo1(){
        productDao.delete();
        productDao.findAll();
        productDao.findone();
        productDao.save();
        productDao.update();
    }
}

    applicationContext.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" 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.xsd"> <!-- bean definitions here -->

    <!--開啟AspectJ的註解開發,自動代理=====================-->
    <aop:aspectj-autoproxy/>

    <!--目標類==============================================-->
    <bean id="productDao" class="com.windbag.aspectJ.demo1.ProductDao"/>

    <!--定義切面-->
    <bean class="com.windbag.aspectJ.demo1.MyAspectAnno"/>
</beans>

    其余的通知類型

@Aspect
public class MyAspectAnno {
    @Before(value = "myPointcut1()")
    public void before(){
        System.out.println("前置通知==================");
    }

    @AfterReturning(value = "execution(* com.windbag.aspectJ.demo1.ProductDao.update(..))",returning = "result")
    public void afterReturing(Object result){
        System.out.println("後置通知==================" + result);
    }

    @Around(value = "execution(* com.windbag.aspectJ.demo1.ProductDao.delete(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("環繞前通知================");
        /*執行目標方法*/
        Object obj = joinPoint.proceed();
        System.out.println("環繞後通知================");
        return obj;
    }

    @AfterThrowing(value = "execution(* com.windbag.aspectJ.demo1.ProductDao.findone(..))",throwing = "e")
    public void afterThrowing(Throwable e){
        System.out.println("異常拋出通知=============" + e.getMessage());
    }

    @After(value = "execution(* com.windbag.aspectJ.demo1.ProductDao.findAll(..))")
    public void after(){
        System.out.println("最終通知================");
    }

    @Pointcut(value = "execution(* com.windbag.aspectJ.demo1.ProductDao.save(..))")
    private void myPointcut1(){

    }
}

基於AspectJ的XML方式的AOP開發

  案例

技術分享圖片

    CustomerDao

public interface CustomerDao {
    public void save();
    public String update();
    public void delete();
    public void findOne();
    public void findAll();
}

      CustomerImpl

public class CustomerDaoImpl implements CustomerDao {
    @Override
    public void save() {
        System.out.println("保存客戶");
    }

    @Override
    public String update() {
        System.out.println("修改客戶");
        return "hello";
    }

    @Override
    public void delete() {
        System.out.println("刪除客戶");
    }

    @Override
    public void findOne() {
        System.out.println("查詢一個客戶");
        //int a = 1/0;
    }

    @Override
    public void findAll() {
        System.out.println("查詢多個客戶");
    }
}

      SpringDemo2Test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringDemo2Test {

    @Resource(name="customerDao")
    private CustomerDao customerDao;

    @Test
    public void demo1(){
        customerDao.save();
        customerDao.delete();
        customerDao.findAll();
        customerDao.findOne();
        customerDao.update();
    }
}

    MyAspectXml

public class MyAspectXml {
    //前置通知
    public void before(JoinPoint joinPoint){
        System.out.println("XML方式的前置通知" + joinPoint);
    }
    //後置通知
    public void afterReturing(Object result){
        System.out.println("XML方式的後置通知" + result);
    }
    //環繞通知
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("XML方式的環繞前通知");
        Object obj = joinPoint.proceed();
        System.out.println("XML方式的環繞後通知");
        return obj;
    }
    //異常拋出通知
    public void afterThrowing(Throwable e){
        System.out.println("XML方式的異常拋出通知" + e.getMessage());
    }
    //最終通知
    public void after(){
        System.out.println("XML方式的最終通知");
    }
}

    applicationContext2.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" 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.xsd"> <!-- bean definitions here -->
    <!--XML的配置方式完成AOP的開發-->
    <!--配置目標類================-->
    <bean id="customerDao" class="com.windbag.aspectJ.demo2.CustomerDaoImpl"/>

    <!--配置切面類-->
    <bean id="myAspectXml" class="com.windbag.aspectJ.demo2.MyAspectXml"/>

    <!--aop的相關配置============-->
    <aop:config>
        <!--配置切入點-->
        <aop:pointcut id="pointcut1" expression="execution(* com.windbag.aspectJ.demo2.CustomerDao.save(..))"/>
        <aop:pointcut id="pointcut2" expression="execution(* com.windbag.aspectJ.demo2.CustomerDao.update(..))"/>
        <aop:pointcut id="pointcut3" expression="execution(* com.windbag.aspectJ.demo2.CustomerDao.delete(..))"/>
        <aop:pointcut id="pointcut4" expression="execution(* com.windbag.aspectJ.demo2.CustomerDao.findOne(..))"/>
        <aop:pointcut id="pointcut5" expression="execution(* com.windbag.aspectJ.demo2.CustomerDao.findAll(..))"/>
        <!--配置AOP的切面-->
        <aop:aspect ref="myAspectXml">
            <!--配置前置增強-->
            <aop:before method="before" pointcut-ref="pointcut1"/>
            <!--配置後置增強-->
            <aop:after-returning method="afterReturing" pointcut-ref="pointcut2" returning="result"/>
            <!--配置環繞增強-->
            <aop:around method="around" pointcut-ref="pointcut3"/>
            <!--配置異常拋出-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"/>
            <!--配置增強-->
            <aop:after method="after" pointcut-ref="pointcut5"/>
        </aop:aspect>

    </aop:config>
</beans>

項目源碼

https://github.com/ryanxu47/spring_aspect

Spring--基於AspectJ的AOP開發