2018-7-1 Spring(16)- AOP-使用XML實現
首先說明,使用XML實現AOP比利用Annotation實現AOP的應用更加廣泛。因為很多切面類(也就是包含織入邏輯的類)我們並沒有源碼,所以也就不可能在源碼上添加Annotation,此時只有通過XML來實現織入切面邏輯。
理論請參考Core Technologies
【實現方法一】
1.修改beans.xml,注意:去除AOP的Annotation使用的<aop:aspectj-autoproxy/>
<?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:annotation-config/> <context:component-scan base-package="com.mytest"/> <!-- 初始化類 --> <bean id="logInterceptor" class="com.mytest.aop.LogInterceptor"></bean> <aop:config> <!-- 定義全局切面/織入點pointcut,即service類的add方法, 切面的名稱為servicePointcut--> <aop:pointcut expression="execution(public * com.mytest.service..*.add(..))" id="servicePointcut"/> <!-- 申明切面對象為logInterceptor --> <aop:aspect id="logAspect" ref="logInterceptor"> <!-- 定義一個織入方法,以及它的織入點, 即在servicePointcut之前加入logInterceptor的before方法--> <aop:before method="before" pointcut-ref="servicePointcut"/> </aop:aspect> </aop:config></beans>
2.修改日誌攔截類,不再需要AOP的Annotation
package com.mytest.aop;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;public class LogInterceptor { public void before() { System.out.println("method start"); } public void afterReturing() { System.out.println("method after returning"); } public void afterThrowing() { System.out.println("method after throwing"); } public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("method around start"); pjp.proceed(); System.out.println("method around end"); }}
3.運行測試類
package com.mytest.service;import org.junit.jupiter.api.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.mytest.model.User;class UserServiceTest { @Test void testAdd() throws Exception { ClassPathXmlApplicationContext factory =new ClassPathXmlApplicationContext("beans.xml"); UserService service=(UserService)factory.getBean("userService"); System.out.println(service.getClass()); service.add(new User()); factory.destroy(); }}
結果
class com.mytest.service.UserService$$EnhancerBySpringCGLIB$$2ff97120method startA user saved.
分析
step1. <context:annotation-config/>,採用Annotaion方法配置IOC。參考2018-6-15 Spring(9)- IOC常用Annotation(@Autowired,@Qualifier, @Required)
step2. <context:component-scan base-package="com.mytest"/>,容器自動去com.mytest目錄下所有包中尋找類並注入bean中。由於UserService和UserDAOImpl類都標註了@Component,所以被容器初始化為對象,並放入容器中。參考2018-6-16 Spring(10)- IOC常用Annotation(@Resource,@Component,Service,Controller,Respository)
step3. 初始化了切面邏輯類對象logInterceptor
step4. 讀取AOP的config
step5. 當運行測試類時候,執行servcei的add方法,spring會發現符合織入點servicePointcut的表達式.並根據定義,找到了定義在這個表達式上的切面logAspect.這個切面引用的對象是容器中的logInterceptor.
step6. 根據切面logAspect配置中的定義,在service類的add方法之前會執行logInterceptor的before方法.
【實現方法二】
beans.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: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:annotation-config/> <context:component-scan base-package="com.mytest"/> <!-- 初始化類 --> <bean id="logInterceptor" class="com.mytest.aop.LogInterceptor"></bean> <aop:config> <!-- 申明切面對象為logInterceptor --> <aop:aspect id="logAspect" ref="logInterceptor"> <!-- 定義一個織入方法,以及它的織入點, 即在servicePointcut之前加入logInterceptor的before方法--> <aop:before method="before" pointcut="execution(public * com.mytest.service..*.add(..))"/> </aop:aspect> </aop:config></beans>
表達式可以直接寫在織入方法定義內,執行效果一樣。
推薦閱讀:
※關於能否基於XML重新實現TeX?
※vb.net如何讀取xml文件里子節點的內容?
※SpringBoot 快速整合Mybatis(去XML化+註解進階)
※如何將DataTable轉為xml