Spring【AOP模塊】就是這么簡單

前言

到目前為止贞奋,已經(jīng)簡單學(xué)習(xí)了Spring的Core模塊内狸、....于是我們就開啟了Spring的AOP模塊了...在講解AOP模塊之前欠肾,首先我們來講解一下cglib代理忱详、以及怎么手動實現(xiàn)AOP編程

cglib代理

在講解cglib之前虚汛,首先我們來回顧一下靜態(tài)代理和動態(tài)代理....我之前就寫過了靜態(tài)代理匾浪、動態(tài)代理的博文:http://blog.csdn.net/hon_3y/article/details/70655966

由于靜態(tài)代理需要實現(xiàn)目標(biāo)對象的相同接口,那么可能會導(dǎo)致代理類會非常非常多....不好維護(hù)---->因此出現(xiàn)了動態(tài)代理

動態(tài)代理也有個約束:目標(biāo)對象一定是要有接口的卷哩,沒有接口就不能實現(xiàn)動態(tài)代理.....----->因此出現(xiàn)了cglib代理

cglib代理也叫子類代理蛋辈,從內(nèi)存中構(gòu)建出一個子類來擴(kuò)展目標(biāo)對象的功能!

  • CGLIB是一個強(qiáng)大的高性能的代碼生成包将谊,它可以在運(yùn)行期擴(kuò)展Java類與實現(xiàn)Java接口冷溶。它廣泛的被許多AOP的框架使用,例如Spring AOP和dynaop尊浓,為他們提供方法的interception(攔截)逞频。

編寫cglib代理

接下來我們就講講怎么寫cglib代理:

  • 需要引入cglib – jar文件, 但是spring的核心包中已經(jīng)包括了cglib功能栋齿,所以直接引入spring-core-3.2.5.jar即可苗胀。
  • 引入功能包后,就可以在內(nèi)存中動態(tài)構(gòu)建子類
  • 代理的類不能為final瓦堵,否則報錯【在內(nèi)存中構(gòu)建子類來做擴(kuò)展基协,當(dāng)然不能為final,有final就不能繼承了】
  • 目標(biāo)對象的方法如果為final/static, 那么就不會被攔截菇用,即不會執(zhí)行目標(biāo)對象額外的業(yè)務(wù)方法澜驮。
//需要實現(xiàn)MethodInterceptor接口
public class ProxyFactory implements MethodInterceptor{

    // 維護(hù)目標(biāo)對象
    private Object target;
    public ProxyFactory(Object target){
        this.target = target;
    }

    // 給目標(biāo)對象創(chuàng)建代理對象
    public Object getProxyInstance(){
        //1\. 工具類
        Enhancer en = new Enhancer();
        //2\. 設(shè)置父類
        en.setSuperclass(target.getClass());
        //3\. 設(shè)置回調(diào)函數(shù)
        en.setCallback(this);
        //4\. 創(chuàng)建子類(代理對象)
        return en.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {

        System.out.println("開始事務(wù).....");

        // 執(zhí)行目標(biāo)對象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事務(wù).....");

        return returnValue;
    }

}
  • 測試:

public class App {

    public static void main(String[] args) {

        UserDao userDao = new UserDao();

        UserDao factory = (UserDao) new ProxyFactory(userDao).getProxyInstance();

        factory.save();
    }
}
這里寫圖片描述
這里寫圖片描述

使用cglib就是為了彌補(bǔ)動態(tài)代理的不足【動態(tài)代理的目標(biāo)對象一定要實現(xiàn)接口】


手動實現(xiàn)AOP編程

AOP 面向切面的編程:

  • AOP可以實現(xiàn)“業(yè)務(wù)代碼”與“關(guān)注點代碼”分離

下面我們來看一段代碼:


// 保存一個用戶
public void add(User user) { 
        Session session = null; 
        Transaction trans = null; 
        try { 
            session = HibernateSessionFactoryUtils.getSession();   // 【關(guān)注點代碼】
            trans = session.beginTransaction();    // 【關(guān)注點代碼】

            session.save(user);     // 核心業(yè)務(wù)代碼

            trans.commit();     //…【關(guān)注點代碼】

        } catch (Exception e) {     
            e.printStackTrace(); 
            if(trans != null){ 
                trans.rollback();   //..【關(guān)注點代碼】

            } 
        } finally{ 
            HibernateSessionFactoryUtils.closeSession(session);   ////..【關(guān)注點代碼】

        } 
   } 
  • 關(guān)注點代碼,就是指重復(fù)執(zhí)行的代碼惋鸥。
  • 業(yè)務(wù)代碼與關(guān)注點代碼分離泉唁,好處?
    • 關(guān)注點代碼寫一次即可揩慕;
    • 開發(fā)者只需要關(guān)注核心業(yè)務(wù)亭畜;
    • 運(yùn)行時期,執(zhí)行核心業(yè)務(wù)代碼時候動態(tài)植入關(guān)注點代碼迎卤; 【代理】

案例分析:

  • IUser接口

public interface IUser {

    void save();
}

我們一步一步來分析拴鸵,首先我們的UserDao有一個save()方法,每次都要開啟事務(wù)和關(guān)閉事務(wù)


//@Component  -->任何地方都能用這個
@Repository  //-->這個在Dao層中使用
    public class UserDao {

    public void save() {

        System.out.println("開始事務(wù)");
        System.out.println("DB:保存用戶");
        System.out.println("關(guān)閉事務(wù)");

    }

}
  • 在剛學(xué)習(xí)java基礎(chǔ)的時候,我們知道:如果某些功能經(jīng)常需要用到就封裝成方法:

//@Component  -->任何地方都能用這個
@Repository  //-->這個在Dao層中使用
    public class UserDao {

    public void save() {

        begin();
        System.out.println("DB:保存用戶");
        close();

    }

    public void begin() {
        System.out.println("開始事務(wù)");
    }
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }
}
  • 現(xiàn)在呢劲藐,我們可能有多個Dao八堡,都需要有開啟事務(wù)和關(guān)閉事務(wù)的功能,現(xiàn)在只有UserDao中有這兩個方法聘芜,重用性還是不夠高兄渺。因此我們抽取出一個類出來

public class AOP {

    public void begin() {
        System.out.println("開始事務(wù)");
    }
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }
}
  • 在UserDao維護(hù)這個變量,要用的時候汰现,調(diào)用方法就行了挂谍。

@Repository  //-->這個在Dao層中使用
public class UserDao {

    AOP aop;

    public void save() {

        aop.begin();
        System.out.println("DB:保存用戶");
        aop.close();

    }

}
  • 現(xiàn)在的開啟事務(wù)、關(guān)閉事務(wù)還是需要我在userDao中手動調(diào)用瞎饲。還是不夠優(yōu)雅口叙。。我想要的效果:當(dāng)我在調(diào)用userDao的save()方法時嗅战,動態(tài)地開啟事務(wù)妄田、關(guān)閉事務(wù)。因此驮捍,我們就用到了代理疟呐。當(dāng)然了,真正執(zhí)行方法的都是userDao东且、要干事的是AOP萨醒,因此在代理中需要維護(hù)他們的引用
public class ProxyFactory {
    //維護(hù)目標(biāo)對象
    private static Object target;

    //維護(hù)關(guān)鍵點代碼的類
    private static AOP aop;
    public static Object getProxyInstance(Object target_, AOP aop_) {

        //目標(biāo)對象和關(guān)鍵點代碼的類都是通過外界傳遞進(jìn)來
        target = target_;
        aop = aop_;

        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        aop.begin();
                        Object returnValue = method.invoke(target, args);
                        aop.close();

                        return returnValue;
                    }
                }
        );
    }
}

工廠靜態(tài)方法:

  • 把AOP加入IOC容器中

//把該對象加入到容器中
@Component
public class AOP {

    public void begin() {
        System.out.println("開始事務(wù)");
    }
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }
}
  • 把UserDao放入容器中

@Component
public class UserDao {

    public void save() {

        System.out.println("DB:保存用戶");

    }

}
  • 在配置文件中開啟注解掃描,使用工廠靜態(tài)方法創(chuàng)建代理對象

<?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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       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">

    <bean id="proxy" class="aa.ProxyFactory" factory-method="getProxyInstance">
        <constructor-arg index="0" ref="userDao"/>
        <constructor-arg index="1" ref="AOP"/>
    </bean>

    <context:component-scan base-package="aa"/>

</beans>
  • 測試苇倡,得到UserDao對象富纸,調(diào)用方法

public class App {

    public static void main(String[] args) {

        ApplicationContext ac =
                new ClassPathXmlApplicationContext("aa/applicationContext.xml");

        IUser iUser = (IUser) ac.getBean("proxy");

        iUser.save();

    }
}
這里寫圖片描述

工廠非靜態(tài)方法

上面使用的是工廠靜態(tài)方法來創(chuàng)建代理類對象。我們也使用一下非靜態(tài)的工廠方法創(chuàng)建對象旨椒。


package aa;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by ozc on 2017/5/11.
 */

public class ProxyFactory {

    public Object getProxyInstance(final Object target_, final AOP aop_) {

        //目標(biāo)對象和關(guān)鍵點代碼的類都是通過外界傳遞進(jìn)來

        return Proxy.newProxyInstance(
                target_.getClass().getClassLoader(),
                target_.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        aop_.begin();
                        Object returnValue = method.invoke(target_, args);
                        aop_.close();

                        return returnValue;
                    }
                }
        );
    }
}

配置文件:先創(chuàng)建工廠晓褪,再創(chuàng)建代理類對象

<?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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       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">

    <!--創(chuàng)建工廠-->
    <bean id="factory" class="aa.ProxyFactory"/>

    <!--通過工廠創(chuàng)建代理-->
    <bean id="IUser" class="aa.IUser" factory-bean="factory" factory-method="getProxyInstance">
        <constructor-arg index="0" ref="userDao"/>
        <constructor-arg index="1" ref="AOP"/>
    </bean>

    <context:component-scan base-package="aa"/>

</beans>
這里寫圖片描述

AOP的概述

Aop: aspect object programming 面向切面編程

  • 功能: 讓關(guān)注點代碼與業(yè)務(wù)代碼分離!
  • 面向切面編程就是指: 對很多功能都有的重復(fù)的代碼抽取综慎,再在運(yùn)行的時候往業(yè)務(wù)方法上動態(tài)植入“切面類代碼”涣仿。

關(guān)注點:

  • 重復(fù)代碼就叫做關(guān)注點。

// 保存一個用戶
public void add(User user) { 
        Session session = null; 
        Transaction trans = null; 
        try { 
            session = HibernateSessionFactoryUtils.getSession();   // 【關(guān)注點代碼】
            trans = session.beginTransaction();    // 【關(guān)注點代碼】

            session.save(user);     // 核心業(yè)務(wù)代碼

            trans.commit();     //…【關(guān)注點代碼】

        } catch (Exception e) {     
            e.printStackTrace(); 
            if(trans != null){ 
                trans.rollback();   //..【關(guān)注點代碼】

            } 
        } finally{ 
            HibernateSessionFactoryUtils.closeSession(session);   ////..【關(guān)注點代碼】

        } 
   } 

切面:

  • 關(guān)注點形成的類示惊,就叫切面(類)好港!

public class AOP {

    public void begin() {
        System.out.println("開始事務(wù)");
    }
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }
}

切入點:

  • 執(zhí)行目標(biāo)對象方法,動態(tài)植入切面代碼米罚。
  • 可以通過切入點表達(dá)式钧汹,指定攔截哪些類的哪些方法; 給指定的類在運(yùn)行的時候植入切面類代碼录择。

切入點表達(dá)式:

  • 指定哪些類的哪些方法被攔截

使用Spring AOP開發(fā)步驟

1) 先引入aop相關(guān)jar文件 (aspectj aop優(yōu)秀組件)

  • spring-aop-3.2.5.RELEASE.jar 【spring3.2源碼】
  • aopalliance.jar 【spring2.5源碼/lib/aopalliance】
  • aspectjweaver.jar 【spring2.5源碼/lib/aspectj】或【aspectj-1.8.2\lib】
  • aspectjrt.jar 【spring2.5源碼/lib/aspectj】或【aspectj-1.8.2\lib】

注意: 用到spring2.5版本的jar文件拔莱,如果用jdk1.7可能會有問題碗降。

  • 需要升級aspectj組件,即使用aspectj-1.8.2版本中提供jar文件提供塘秦。

2) bean.xml中引入aop名稱空間

  • xmlns:context="http://www.springframework.org/schema/context"
  • http://www.springframework.org/schema/context
  • http://www.springframework.org/schema/context/spring-context.xsd

引入jar包

引入4個jar包:

這里寫圖片描述

引入名稱空間


<?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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       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">

</beans>

注解方式實現(xiàn)AOP編程

我們之前手動的實現(xiàn)AOP編程是需要自己來編寫代理工廠的讼渊,現(xiàn)在有了Spring,就不需要我們自己寫代理工廠了尊剔。Spring內(nèi)部會幫我們創(chuàng)建代理工廠爪幻。

  • 也就是說,不用我們自己寫代理對象了须误。

因此挨稿,我們只要關(guān)心切面類、切入點霹期、編寫切入表達(dá)式指定攔截什么方法就可以了叶组!

還是以上一個例子為案例拯田,使用Spring的注解方式來實現(xiàn)AOP編程

在配置文件中開啟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:p="http://www.springframework.org/schema/p"
       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="aa"/>

    <!-- 開啟aop注解方式 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

代碼:

  • 切面類

@Component
@Aspect//指定為切面類
public class AOP {

    //里面的值為切入點表達(dá)式
    @Before("execution(* aa.*.*(..))")
    public void begin() {
        System.out.println("開始事務(wù)");
    }

    @After("execution(* aa.*.*(..))")
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }
}
  • UserDao實現(xiàn)了IUser接口

@Component
public class UserDao implements IUser {

    @Override
    public void save() {
        System.out.println("DB:保存用戶");
    }

}
  • IUser接口

public interface IUser {
    void save();
}
  • 測試代碼:

public class App {

    public static void main(String[] args) {

        ApplicationContext ac =
                new ClassPathXmlApplicationContext("aa/applicationContext.xml");

        //這里得到的是代理對象....
        IUser iUser = (IUser) ac.getBean("userDao");

        System.out.println(iUser.getClass());

        iUser.save();

    }
}
這里寫圖片描述

目標(biāo)對象沒有接口

上面我們測試的是UserDao有IUser接口历造,內(nèi)部使用的是動態(tài)代理...那么我們這次測試的是目標(biāo)對象沒有接口

  • OrderDao沒有實現(xiàn)接口

@Component
public class OrderDao {

    public void save() {

        System.out.println("我已經(jīng)進(jìn)貨了!4印吭产!");

    }
}
  • 測試代碼:

public class App {

    public static void main(String[] args) {

        ApplicationContext ac =
                new ClassPathXmlApplicationContext("aa/applicationContext.xml");

        OrderDao orderDao = (OrderDao) ac.getBean("orderDao");

        System.out.println(orderDao.getClass());

        orderDao.save();

    }
}

這里寫圖片描述

優(yōu)化和AOP注解API

API:

  • @Aspect 指定一個類為切面類

  • @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入點表達(dá)式

  • @Before("pointCut_()") 前置通知: 目標(biāo)方法之前執(zhí)行

  • @After("pointCut_()") 后置通知:目標(biāo)方法之后執(zhí)行(始終執(zhí)行)

  • @AfterReturning("pointCut_()") 返回后通知: 執(zhí)行方法結(jié)束前執(zhí)行(異常不執(zhí)行)

  • @AfterThrowing("pointCut_()") 異常通知: 出現(xiàn)異常時候執(zhí)行

  • @Around("pointCut_()") 環(huán)繞通知: 環(huán)繞目標(biāo)方法執(zhí)行

  • 測試:


    // 前置通知 : 在執(zhí)行目標(biāo)方法之前執(zhí)行
    @Before("pointCut_()")
    public void begin(){
        System.out.println("開始事務(wù)/異常");
    }

    // 后置/最終通知:在執(zhí)行目標(biāo)方法之后執(zhí)行  【無論是否出現(xiàn)異常最終都會執(zhí)行】
    @After("pointCut_()")
    public void after(){
        System.out.println("提交事務(wù)/關(guān)閉");
    }

    // 返回后通知: 在調(diào)用目標(biāo)方法結(jié)束后執(zhí)行 【出現(xiàn)異常不執(zhí)行】
    @AfterReturning("pointCut_()")
    public void afterReturning() {
        System.out.println("afterReturning()");
    }

    // 異常通知: 當(dāng)目標(biāo)方法執(zhí)行異常時候執(zhí)行此關(guān)注點代碼
    @AfterThrowing("pointCut_()")
    public void afterThrowing(){
        System.out.println("afterThrowing()");
    }

    // 環(huán)繞通知:環(huán)繞目標(biāo)方式執(zhí)行
    @Around("pointCut_()")
    public void around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("環(huán)繞前....");
        pjp.proceed();  // 執(zhí)行目標(biāo)方法
        System.out.println("環(huán)繞后....");
    }

優(yōu)化

我們的代碼是這樣的:每次寫B(tài)efore、After等鸭轮,都要重寫一次切入點表達(dá)式臣淤,這樣就不優(yōu)雅了。


    @Before("execution(* aa.*.*(..))")
    public void begin() {
        System.out.println("開始事務(wù)");
    }

    @After("execution(* aa.*.*(..))")
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }

于是乎窃爷,我們要**使用@Pointcut這個注解邑蒋,來指定切入點表達(dá)式,在用到的地方中按厘,直接引用就行了医吊!**

  • 那么我們的代碼就可以改造成這樣了:

@Component
@Aspect//指定為切面類
public class AOP {

    // 指定切入點表達(dá)式,攔截哪個類的哪些方法
    @Pointcut("execution(* aa.*.*(..))")
    public void pt() {

    }

    @Before("pt()")
    public void begin() {
        System.out.println("開始事務(wù)");
    }

    @After("pt()")
    public void close() {
        System.out.println("關(guān)閉事務(wù)");
    }
}


XML方式實現(xiàn)AOP編程

首先逮京,我們把所有的注解都去掉...

  • 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:p="http://www.springframework.org/schema/p"
       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">

    <!--對象實例-->
    <bean id="userDao" class="aa.UserDao"/>
    <bean id="orderDao" class="aa.OrderDao"/>

    <!--切面類-->
    <bean id="aop" class="aa.AOP"/>

    <!--AOP配置-->
    <aop:config >

        <!--定義切入表達(dá)式卿堂,攔截哪些方法-->
        <aop:pointcut id="pointCut" expression="execution(* aa.*.*(..))"/>

        <!--指定切面類是哪個-->
        <aop:aspect ref="aop">

            <!--指定來攔截的時候執(zhí)行切面類的哪些方法-->
            <aop:before method="begin" pointcut-ref="pointCut"/>
            <aop:after method="close" pointcut-ref="pointCut"/>

        </aop:aspect>
    </aop:config>

</beans>
  • 測試:

public class App {

    @Test
    public  void test1() {

        ApplicationContext ac =
                new ClassPathXmlApplicationContext("aa/applicationContext.xml");

        OrderDao orderDao = (OrderDao) ac.getBean("orderDao");

        System.out.println(orderDao.getClass());

        orderDao.save();

    }

    @Test
    public  void test2() {

        ApplicationContext ac =
                new ClassPathXmlApplicationContext("aa/applicationContext.xml");

        IUser userDao = (IUser) ac.getBean("userDao");

        System.out.println(userDao.getClass());

        userDao.save();

    }
}

測試OrderDao

這里寫圖片描述

測試UserDao

這里寫圖片描述

切入點表達(dá)式

切入點表達(dá)式主要就是來配置攔截哪些類的哪些方法

查官方文檔

..我們?nèi)ノ臋n中找找它的語法...

這里寫圖片描述

在文檔中搜索:execution(

這里寫圖片描述

語法解析

那么它的語法是這樣子的:


execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

符號講解:

  • ?號代表0或1,可以不寫
  • ”號代表任意類型懒棉,0或多*
  • 方法參數(shù)為..表示為可變參數(shù)

參數(shù)講解:

  • modifiers-pattern?【修飾的類型草描,可以不寫】
  • ret-type-pattern【方法返回值類型,必寫】
  • declaring-type-pattern?【方法聲明的類型策严,可以不寫】
  • name-pattern(param-pattern)【要匹配的名稱穗慕,括號里面是方法的參數(shù)】
  • throws-pattern?【方法拋出的異常類型,可以不寫】

官方也有給出一些例子給我們理解:

這里寫圖片描述

測試代碼


        <!-- 【攔截所有public方法】 -->
        <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->

        <!-- 【攔截所有save開頭的方法 】 -->
        <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->

        <!-- 【攔截指定類的指定方法, 攔截時候一定要定位到方法】 -->
        <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->

        <!-- 【攔截指定類的所有方法】 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->

        <!-- 【攔截指定包妻导,以及其自包下所有類的所有方法】 -->
        <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->

        <!-- 【多個表達(dá)式】 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <!-- 下面2個且關(guān)系的揍诽,沒有意義 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) &amp;&amp; execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->

        <!-- 【取非值】 -->
        <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->

如果文章有錯的地方歡迎指正诀蓉,大家互相交流。習(xí)慣在微信看技術(shù)文章暑脆,想要獲取更多的Java資源的同學(xué)渠啤,可以關(guān)注微信公眾號:Java3y

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市添吗,隨后出現(xiàn)的幾起案子沥曹,更是在濱河造成了極大的恐慌,老刑警劉巖碟联,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妓美,死亡現(xiàn)場離奇詭異,居然都是意外死亡鲤孵,警方通過查閱死者的電腦和手機(jī)壶栋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來普监,“玉大人贵试,你說我怎么就攤上這事】” “怎么了毙玻?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長廊散。 經(jīng)常有香客問我桑滩,道長,這世上最難降的妖魔是什么允睹? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任运准,我火速辦了婚禮,結(jié)果婚禮上缭受,老公的妹妹穿的比我還像新娘胁澳。我一直安慰自己,他們只是感情好贯涎,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布听哭。 她就那樣靜靜地躺著,像睡著了一般塘雳。 火紅的嫁衣襯著肌膚如雪陆盘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天败明,我揣著相機(jī)與錄音隘马,去河邊找鬼。 笑死妻顶,一個胖子當(dāng)著我的面吹牛酸员,可吹牛的內(nèi)容都是我干的蜒车。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼幔嗦,長吁一口氣:“原來是場噩夢啊……” “哼酿愧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邀泉,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤嬉挡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后汇恤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庞钢,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年因谎,在試婚紗的時候發(fā)現(xiàn)自己被綠了基括。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡财岔,死狀恐怖风皿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情使鹅,我是刑警寧澤揪阶,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布昌抠,位于F島的核電站患朱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏炊苫。R本人自食惡果不足惜裁厅,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侨艾。 院中可真熱鬧执虹,春花似錦、人聲如沸唠梨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽当叭。三九已至茬故,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚁鳖,已是汗流浹背磺芭。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留醉箕,地道東北人钾腺。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓徙垫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親放棒。 傳聞我的和親對象是個殘疾皇子姻报,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353