Java--簡單的Spring AOP配置以及AOP事物管理,JDK/GCLib動態代理


一、看一下簡單的通過XML的AOP配置

1.首先創建一個簡單的Student類

public class Student {
    private Integer age;
    private String name;

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        System.out.println("Age : " + age);
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        System.out.println("Name : " + name);
        return name;
    }

    public void printThrowException() {
        System.out.println("Exception raised");
        throw new IllegalArgumentException();
    }
}

2.創建一個簡單的aspect切面class

public class Logging {/**
     * This is the method which I would like to execute
     * before a selected method execution.
     */public void beforeAdvice() {
        System.out.println("Going to setup student profile.");
    }

    /**
     * This is the method which I would like to execute
     * after a selected method execution.
     */public void afterAdvice() {
        System.out.println("Student profile has been setup.");
    }

    /**
     * This is the method which I would like to execute
     * when any method returns.
     */
    public void afterReturningAdvice(Object retVal) {
        System.out.println("Returning:" + retVal.toString());
    }

    /**
     * This is the method which I would like to execute
     * if there is an exception raised.
     */
    public void AfterThrowingAdvice(IllegalArgumentException ex) {
        System.out.println("There has been an exception: " + ex.toString());
    }
}

3.SpringAOP.xml配置

    <bean id="student" class="com.seeyon.SpringBean.aop.Student" p:name="yangyu" p:age="27"></bean>
    <bean id="logging" class="com.seeyon.SpringBean.aop.Logging"></bean>

    <!--XML方式配置Spring AOP-->
    <aop:config>
        <aop:aspect id="log" ref="logging">   【切面class】
            <aop:pointcut id="studentMethod" expression="execution(* com.seeyon.SpringBean.aop.Student.get*(..))"/> 【切點】
            <aop:before pointcut-ref="studentMethod" method="beforeAdvice"/>  【方法執行之前觸發切面class的beforeAdvice方法】
            <aop:after pointcut-ref="studentMethod" method="afterAdvice"/>    【方法執行之后觸發切面class的afterAdvice方法】
        </aop:aspect>
    </aop:config>

分析一下這個execution(* com.seeyon.SpringBean.aop.Student.get*(..))切點表達式:

(1)第一個*代表方法的返回值是任意的

(2)get*代表以get開頭的所有方法

(3)(..)代表方法的參數是任意個數

 

4.main方法

public class test {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("SpringAop.xml");
        Student student = (Student) context.getBean("student");
        student.getName();
//        student.getAge();
//        student.printThrowException();
    }
}

5.輸出結果

Going to setup student profile.
Name : yangyu
Student profile has been setup.

 

二、Spring AOP注解的使用。

1.首先創建一個簡單的Student類(同一.1中,請看上面👆)

2.創建一個簡單的aspect切面class,並加上@注解配置。

@Aspect   //表示是一個aspect切面class,注解以后可以被Spring掃描到
public class Logging {

    @Pointcut("execution(* com.seeyon.SpringBean.aop.Student.get*(..))")  //定義切點
    public void getMethod(){}; //切點方法,方法名稱相當於ID,方法名稱隨便取

    /**
     * This is the method which I would like to execute
     * before a selected method execution.
     */
    @Before("getMethod()")   //切點方法執行之前執行@Before
    public void beforeAdvice() {
        System.out.println("Going to setup student profile.");
    }

    /**
     * This is the method which I would like to execute
     * after a selected method execution.
     */
    @After("getMethod()")   //切點方法執行之后執行@After
    public void afterAdvice() {
        System.out.println("Student profile has been setup.");
    }

    /**
     * This is the method which I would like to execute
     * when any method returns.
     */
    @AfterReturning(pointcut = "getMethod()",returning = "retVal")//切點方法返回值完成后執行@AfterReturning
    public void afterReturningAdvice(Object retVal) {
        System.out.println("Returning:" + retVal.toString());
    }

    /**
     * This is the method which I would like to execute
     * if there is an exception raised.
     */
    @AfterThrowing(pointcut = "getMethod()",throwing = "ex")//切點方法拋出異常之后執行@AfterThrowing
    public void AfterThrowingAdvice(IllegalArgumentException ex) {
        System.out.println("There has been an exception: " + ex.toString());
    }
}

3.SpringAOP.xml配置

    <bean id="student" class="com.seeyon.SpringBean.aop.Student" p:name="yangyu" p:age="27"></bean>
    <bean id="logging" class="com.seeyon.SpringBean.aop.Logging"></bean>

    <!--注解方式配置Spring AOP,Spring會自動到已注冊的bean中去尋找@Aspect注解標記的class-->
    <aop:aspectj-autoproxy/>

4.mian方法

public class test {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("SpringAop.xml");
        Student student = (Student) context.getBean("student");
        student.getName();
//        student.getAge();
//        student.printThrowException();
    }
}

5.輸出結果

Going to setup student profile.
Name : yangyu
Student profile has been setup.
Returning:yangyu

 

注意事項:

<aop:config proxy-target-class="true">
</aop:config>

<aop:aspectj-autoproxy proxy-target-class="true"/>

1.如果不設置proxy-target-class屬性或者設置成false:

(1)代理類實現了接口,那么AOP實際上是使用的JDK的自動代理,代理的接口。

(2)代理類沒有接口,那么還是使用的CGLib進行代理。

 

2.如果將proxy-target-class屬性設置成true,那么將始終使用CGLib進行代理。

 

JDK動態代理與CGLib動態區別:

1、JDK動態代理:JDK的動態代理依靠接口實現,如果有些類並沒有實現接口,則不能使用JDK代理,這就要使用cglib動態代理了。

2、CGLib動態代理:cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。

 

可以得出一個結論:CGLib 可以代理任何的類。

那為什么還要用 JDK 的動態代理呢?肯定您會這樣問:

根據多年來實際項目經驗得知:CGLib 創建代理的速度比較慢,但創建代理后運行的速度卻非常快,而 JDK 動態代理正好相反。如果在運行的時候不斷地用 CGLib 去創建代理,系統的性能會大打折扣,所以建議一般在系統初始化的時候用 CGLib 去創建代理,並放入 Spring 的ApplicationContext 中以備后用。

 

三、通過AOP進行事務管理

1.SpringAOP.xml配置

    <!--事物管理-->
    <aop:config proxy-target-class="true"> //使用GCLib動態代理模式
        <aop:pointcut id="studentGetMethod"
                      expression="execution(* com.seeyon.SpringBean.aop..*.*(..))" /> //定義切點
        <aop:advisor pointcut-ref="studentGetMethod" advice-ref="txAdvice" />
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="*" />             //對有所方法進行事物管理
        </tx:attributes>
    </tx:advice>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/>

分析一下execution(* com.seeyon.SpringBean.aop..*.*(..))這個切點表達式:

(1)第一個*表示方法的返回值是任意的

(2)aop..表示aop包以及aop的子包

(3)aop..*表示aop包以及aop的子包下的所有class

(4)aop..*.*表示aop包以及aop的子包下的所有class的所有方法

(5)(..)表示方法參數任意

 

此處簡單列舉了一個TransactionManager:org.springframework.jdbc.datasource.DataSourceTransactionManager,並且沒有對其進行屬性注入,請根據自己的項目合理選擇TransactionManager。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM