spring aop與aspectj


AOP:面向切面編程

簡介

AOP解決的問題:將核心業務代碼與外圍業務(日志記錄、權限校驗、異常處理、事務控制)代碼分離出來,提高模塊化,降低代碼耦合度,使職責更單一。

 

AOP應用場景:

日志記錄、權限校驗、異常處理、事務控制等

 

 

相關概念

 

 

圖片來源:

https://raw.githubusercontent.com/WarframePrimer/mysmart4j/master/img/AOP.jpg

 

 

joinPoint:連接點。在spring中只支持方法連接點,連接點指的是可以使用advice(增強)的地方,例如一個類中有5個方法,那么這5個方法,那么這5個方法都可以是連接點。

 

pointcut:切點。可理解為實實在在的連接點,即切入advice(增強)的點。例如

一個類中有5個方法,其中有3個方法(連接點)需要織入advice(增強),那么這3個需要織入advice的連接點就是切點。

 

advice:增強。實際中想要添加的功能,如日志、權限校驗。

before:前置增強,目標方法執行前之前執行。

after:后置增強,目標方法執行后執行。

around:環繞增強,在目標方法執行時執行,可控制目標方法是否執行。

after throwing:異常增強,目標方法拋出異常時執行。

weaving:織入。即對方法的增強,將切面的代碼織入(應用)到目標函數的過程。

introduction advice:引入增強。即對類的增強。

 

advisor:切面。由切點和增強相結合而成,定義增強應用到哪些切點上。

 

Aop的兩種實現

pom.xml依賴

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

 

    <groupId>com.lnjecit</groupId>

    <artifactId>chapter4</artifactId>

    <version>1.0-SNAPSHOT</version>
 

    <properties>

        <spring.version>4.1.7.RELEASE</spring.version>

    </properties>
 

    <dependencies>

        <dependency>

            <groupId>cglib</groupId>

            <artifactId>cglib</artifactId>

            <version>3.2.0</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-aop</artifactId>

            <version>${spring.version}</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-aspects</artifactId>

            <version>${spring.version}</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-beans</artifactId>

            <version>${spring.version}</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-context</artifactId>

            <version>${spring.version}</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-context-support</artifactId>

            <version>${spring.version}</version>

        </dependency>

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-core</artifactId>

            <version>${spring.version}</version>

        </dependency>

    </dependencies>

</project>

  

Spring aop

基於代理(jdk動態代理、cglib動態代理)實現的aop

Spring aop使用了兩種代理機制。一種是jdk動態代理,另一種是cglib動態代理。

Jdk動態代理只支持接口代理,cglib支持類的代理。

 

編程式
前置增強 before advice
前置增強:實現MethodBeforeAdvice接口,執行目標方法前執行before方法
/**
 * 編程式前置增強
 */
public class UserBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Before");
    }
}

 

 后置增強 after advice

后置增強:實現AfterReturningAdvice接口,執行目標方法后執行afterReturning方法

/**
 * 編程式后置增強
 */
public class UserAfterAdvice implements  AfterReturningAdvice  {
 
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("After");
    }
}

 

 

環繞增強 around advice

環繞增強:實現MethodInterceptor接口,執行目標方法前后執行invoke方法

/**
 * 編程式環繞增強
 **/
public class UserAroundAdvice implements MethodInterceptor{
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Before");
        Object result = invocation.proceed();
        System.out.println("After");
        return result;
    }
}

 

 

用戶服務接口類:

public interface UserService { 
    void queryAll();
}

 

 

用戶服務接口實現類:

public class UserServiceImpl implements UserService {
 
    @Override
    public void queryAll() {
        System.out.println("查詢全部用戶並返回");
    }
}

  

測試代碼:

public class Test {
 
    public static void main(String[] args) {
        /**
         * 測試前置增強和后置增強
         */
        ProxyFactory proxyFactory = new ProxyFactory();//創建代理工廠
        proxyFactory.setTarget(new UserServiceImpl());//射入目標類對象
        proxyFactory.addAdvice(new UserBeforeAdvice());//添加前置增強
        proxyFactory.addAdvice(new UserAfterAdvice());//添加后置增強
        UserService userService = (UserService) proxyFactory.getProxy();//從代理工廠獲取代理
        userService.queryAll();//調用代理的方法
 
        /**
         * 測試環繞增強
         */
        ProxyFactory proxyFactory2 = new ProxyFactory();//創建代理工廠
        proxyFactory2.setTarget(new UserServiceImpl());//射入目標類對象
        proxyFactory2.addAdvice(new UserAroundAdvice());//添加環繞增強
        UserService userService2 = (UserService) proxyFactory2.getProxy();//從代理工廠獲取代理
        userService2.queryAll();//調用代理的方法
 
    }
}

 

 

聲明式(基於xml配置)
環繞增強 around advice

spring-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: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">
 
    <!--掃描指定包-->
    <context:component-scan base-package="com.lnjecit.chapter4.user"/>
 
    <!--配置代理-->
    <bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--需要代理的接口-->
        <property name="interfaces" value="com.lnjecit.chapter4.user.UserService"/>
        <!--接口實現類-->
        <property name="target" ref="userServiceImpl"/>
        <!--攔截器名稱(即增強類名稱)-->
        <property name="interceptorNames">
            <list>
                <value>userAroundAdvice</value>
            </list>
        </property>
 
    </bean>
 
</beans>

 

 

 

用戶服務接口類:

public interface UserService {
    void queryAll();
}

 

 

用戶服務接口實現類:

@Component
public class UserServiceImpl implements UserService {
 
    @Override
    public void queryAll() {
        System.out.println("查詢全部用戶並返回");
    }
}

 

 

測試環繞增強代碼:

public class Test {
 
    public static void main(String[] args) {
        // 獲取spring context
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aop.xml");
        // 從context中獲取id為userServiceProxy的代理對象
        UserService userServiceProxy = (UserService) applicationContext.getBean("userServiceProxy");
        // 調用代理的方法
        userServiceProxy.queryAll();
 
    }
}

 

  

拋出增強 throws advice

拋出增強:實現ThrowsAdvice接口。當執行目標方法出現異常會執行拋出增強中的afterThrowing方法。

 

/**
 * 拋出增強
 */
@Component
public class UserThrowAdvice implements ThrowsAdvice {
 
    public void afterThrowing(Method method, Object[] args, Object target, Exception e) {
        System.out.println("Throw exception:");
        System.out.println("Target class name:" + target.getClass().getName());
        System.out.println("Method name: " + method.getName());
        System.out.println("Exception message:" + e.getMessage());
    }
}

  

將UserServiceImpl類修改如下:故意拋出運行時異常,用於測試拋出增強

 

@Component
public class UserServiceImpl implements UserService {
 
    @Override
    public void queryAll() {
        System.out.println("查詢全部用戶並返回");
        throw new RuntimeException("Error");
    }
}

  

Spring-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: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">

 

    <!--掃描指定包-->

    <context:component-scan base-package="com.lnjecit.chapter4.user"/>

 

    <!--配置代理-->

    <bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

        <!--需要代理的接口-->

        <property name="interfaces" value="com.lnjecit.chapter4.user.UserService"/>

        <!--接口實現類-->

        <property name="target" ref="userServiceImpl"/>

        <!--攔截器名稱(即增強類名稱)-->

        <property name="interceptorNames">

            <list>

                <value>userThrowAdvice</value>

            </list>

        </property>

    </bean> 

</beans>

 

 

測試代碼與環繞增強的測試代碼相同,不再復制。

 

切面 advisor

advisor(切面)封裝了advice(增強)和pointcut(切點)

 

在UserService接口中添加兩個方法query、save.

UserService代碼如下:

public interface UserService { 

    void queryAll(); 

    void query(); 

    void save();

}

 

 

UserServiceImpl代碼如下:

@Component

public class UserServiceImpl implements UserService { 

    @Override

    public void queryAll() {

        System.out.println("查詢全部用戶並返回");

    }
 

    @Override

    public void query() {

        System.out.println("根據條件查詢用戶");

    }
 

    @Override

    public void save() {

        System.out.println("新增用戶");

    }
 

}

 

 

spring-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: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">

 

    <!--掃描指定包-->

    <context:component-scan base-package="com.lnjecit.chapter4.user"/>

 

    <!--配置一個切面-->

    <bean id="userServiceAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <!--增強-->

        <property name="advice" ref="userAroundAdvice"/>

        <!--切點(正則表達式:匹配UserServiceImpl類中以query開頭的方法)-->

        <property name="pattern" value="com.lnjecit.chapter4.user.UserServiceImpl.query.*"/>

    </bean>

 

    <!--配置代理-->

    <bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

        <!--目標類-->

        <property name="target" ref="userServiceImpl"/>

        <!--切面-->

        <property name="interceptorNames" value="userServiceAdvisor"/>

        <!--代理目標類-->

        <property name="proxyTargetClass" value="true"/>

    </bean>

</beans>

 

 

測試代碼:

 

public class Test {
 

    public static void main(String[] args) {

        // 獲取spring context

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aop.xml");

        // 從context中獲取id為userServiceProxy的代理對象

        UserService userServiceProxy = (UserService) applicationContext.getBean("userServiceProxy");

        // 調用代理的方法

        userServiceProxy.queryAll();

        userServiceProxy.query();

        userServiceProxy.save();

 

    }

}

 

 

 

測試結果如下:

Before

查詢全部用戶並返回

After

Before

根據條件查詢用戶

After

新增用戶

可以看出UserService中的queryAll、query方法被攔截,執行這兩個方法前后執行了環繞增強代碼。而save方法沒有被攔截。

 

自動代理

aspectj

基於注解
環繞增強 around advice

使用@Aspect注解定義切面類UserAdvisor

 

/**

 * 切面

 */

@Aspect

@Component

public class UserAdvisor { 

    @Around("execution(* com.lnjecit.chapter4.user.UserServiceImpl.*(..))")

    public Object arount(ProceedingJoinPoint joinPoint) throws Throwable {

        before();

        Object result = joinPoint.proceed();

        after();

        return result;

    } 

    public void before() {

        System.out.println("Before");

    } 

    public void after() {

        System.out.println("After");

    }

}

 

 

切點表達式:

execution(* com.lnjecit.chapter4.user.UserServiceImpl.*(..))

l  Execution表示要攔截的方法

l  第一個“*”表示方法返回值任意

l  第二個“*”表示匹配類中的所有方法

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

 

spring-aspectj.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:component-scan base-package="com.lnjecit.chapter4.user"/>

 

    <!--默認為false,使用JDK動態代理 設置為true,啟用cglib動態代理-->

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

 

</beans>

 

 

測試代碼:

public class Test {

 

    public static void main(String[] args) {

        // 獲取spring context

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aspectj.xml");

        // 從context中獲取id為userServiceImpl的對象

        UserService userServiceImpl = (UserService) applicationContext.getBean("userServiceImpl");

        userServiceImpl.queryAll();

        userServiceImpl.query();

        userServiceImpl.save();

 

    }

}

 

 

攔截指定注解

簡單案例:使用@Annotation注解攔截Log注解,記錄日志

 

 

定義Log注解

/**

 * 日志注解

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

public @interface Log {
   

}

 

 

定義切面LogAspect

 

 
         
@Aspect
@Component

public class LogAspect {
   @Before(value = "@annotation(com.lnjecit.chapter4.user.Log)")
    public void before(JoinPoint joinPoint) {
        // 目標類名稱
        String targetClazzName = joinPoint.getTarget().getClass().getName();
        // 目標方法名稱
        String targetMethodName = joinPoint.getSignature().getName();
        System.out.println("執行目標方法" + targetClazzName + "." + targetMethodName +"前,記錄日志");
        // 可在此處將日志異步存儲到數據庫表中
    }

}

 

在UserServiceImpl類的save方法上加上Log注解

@Component

public class UserServiceImpl implements UserService { 

    @Override

    public void queryAll() {

        System.out.println("查詢全部用戶並返回");

//        throw new RuntimeException("Error");

    }
 

    @Override

    public void query() {

        System.out.println("根據條件查詢用戶");

    }
 

    @Log

    @Override

    public void save() {

        System.out.println("新增用戶");

    } 

}

 

 

測試代碼:

public class Test {
 

    public static void main(String[] args) {

        // 獲取spring context

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aspectj.xml");

        // 從context中獲取id為userServiceImpl的對象

        UserService userServiceImpl = (UserService) applicationContext.getBean("userServiceImpl");

        userServiceImpl.save();

    }

}

 

 

測試結果如下:

執行目標方法com.lnjecit.chapter4.user.UserServiceImpl.save前,記錄日志
新增用戶

 

根據結果可以看出執行save方法之前,執行了LogAspect中的前置增強。

 

基於配置

除了使用Aspect注解外,還可以使用xml配置的方式來實現aspect的應用

環繞增強 around advice

切面類UserAdvisor

/**
 * 切面
 */
public class UserAdvisor {

    public Object arount(ProceedingJoinPoint joinPoint) throws Throwable {
        before();
        Object result = joinPoint.proceed();
        after();
        return result;
    }

    public void before() {
        System.out.println("Before");
    }

    public void after() {
        System.out.println("After");
    }
}

 

spring-aspectj.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:component-scan base-package="com.lnjecit.chapter4.user"/>

    <bean id="userServiceImpl" class="com.lnjecit.chapter4.user.UserServiceImpl"/>
    <bean id="userAdvisor" class="com.lnjecit.chapter4.user.UserAdvisor"/>

    <aop:config>
        <!--切面-->
        <aop:aspect ref="userAdvisor">
            <!--環繞增強-->
            <aop:around method="arount" pointcut="execution(* com.lnjecit.chapter4.user.UserServiceImpl.*(..))"></aop:around>
        </aop:aspect>
    </aop:config>

</beans>

 

UserServiceImpl:

public class UserServiceImpl implements UserService {

    @Override
    public void queryAll() {
        System.out.println("查詢全部用戶並返回");
    }

    @Override
    public void query() {
        System.out.println("根據條件查詢用戶");
    }

    @Log
    @Override
    public void save() {
        System.out.println("新增用戶");
    }

}

 

 測試代碼:

public class Test {

    public static void main(String[] args) {
        // 獲取spring context
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aspectj.xml");
        // 從context中獲取id為userServiceImpl的對象
        UserService userServiceImpl = (UserService) applicationContext.getBean("userServiceImpl");
        userServiceImpl.queryAll();
        userServiceImpl.query();
        userServiceImpl.save();

    }
}

測試結果與使用注解實現效果相同。

 

攔截指定注解

Log注解:

/**
 * 日志注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Log {

}

 

切面LogAspect:

/**
 * 日志切面
 */
public class LogAspect {

    public void before(JoinPoint joinPoint) {
    // 目標類名稱
String targetClazzName = joinPoint.getTarget().getClass().getName();
// 目標方法名稱
String targetMethodName = joinPoint.getSignature().getName();
System.out.println("執行目標方法" + targetClazzName + "." + targetMethodName +"前,記錄日志");
// 可在此處將日志異步存儲到數據庫表中
 }

 

spring-aspectj.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">

    <bean id="userServiceImpl" class="com.lnjecit.chapter4.user.UserServiceImpl"/>
    <bean id="logAspect" class="com.lnjecit.chapter4.user.LogAspect"/>

    <aop:config>
        <!--切面-->
        <aop:aspect ref="logAspect">
            <!--前置增強-->
            <aop:before method="before" pointcut="@annotation(com.lnjecit.chapter4.user.Log)"></aop:before>
        </aop:aspect>
    </aop:config>

</beans>

 

UserService、UserServiceImpl類與環繞通知中代碼中相同。

 

測試代碼:

public class Test {

    public static void main(String[] args) {
        // 獲取spring context
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aspectj.xml");
        // 從context中獲取id為userServiceImpl的對象
        UserService userServiceImpl = (UserService) applicationContext.getBean("userServiceImpl");
        userServiceImpl.queryAll();
        userServiceImpl.query();
        userServiceImpl.save();

    }
}

 

測試結果與基於注解測試結果相同。

 

Spring aop與aspectJ的區別

1、織入的時期不同

spring aop采用的動態織入,而aspectJ是靜態織入。

靜態織入:指在編譯時期就織入,即:編譯出來的class文件,字節碼就已經被織入了。

動態織入:分靜動兩種,靜則指織入過程只在第一次調用時執行;動則指根據代碼動態運行的中間狀態來決定如何操作,每次調用target的時候都執行。

 

Spring aspectJ簡單應用案例

日志記錄

可參考前面案例中的定義日志記錄,使用切面記錄日志。

性能監控

 定義性能監控切面:

/**
 * 性能監控切面
 */
@Aspect
@Component
public class MonitorAspect {

    @Around("execution(* com.lnjecit.chapter4.user.UserServiceImpl.*(..))")
    public Object arount(ProceedingJoinPoint joinPoint) throws Throwable {
        // 目標類名稱
        String targetClazzName = joinPoint.getTarget().getClass().getName();
        // 目標類方法名稱
        String targetMethodName = joinPoint.getSignature().getName();

        // 計時並調用目標函數
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long time = System.currentTimeMillis() - start;

        System.out.println("執行" + targetClazzName + "." + targetMethodName + "方法耗時" + time + "毫秒");
        // 可在此處將監控信息存儲
        return result;
    }

}

 

 UserService:

public interface UserService {

    void queryAll();

    void query();

    void save();
}

 

UserServiceImpl:

@Component
public class UserServiceImpl implements UserService {

    @Override
    public void queryAll() {
        System.out.println("查詢全部用戶並返回");
    }

    @Override
    public void query() {
        System.out.println("根據條件查詢用戶");
    }

     @Override
    public void save() {
        System.out.println("新增用戶");
    }

 

spring-aspectj.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:component-scan base-package="com.lnjecit.chapter4.user"/>

    <!--默認為false,使用JDK動態代理 設置為true,啟用cglib動態代理-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

</beans>

 

測試代碼:

public class Test {

    public static void main(String[] args) {
        // 獲取spring context
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-aspectj.xml");
        // 從context中獲取id為userServiceImpl的對象
        UserService userServiceImpl = (UserService) applicationContext.getBean("userServiceImpl");
        userServiceImpl.queryAll();
        userServiceImpl.query();
        userServiceImpl.save();
    }
}

 

測試結果如下:

查詢全部用戶並返回
執行com.lnjecit.chapter4.user.UserServiceImpl.queryAll方法耗時54毫秒
根據條件查詢用戶
執行com.lnjecit.chapter4.user.UserServiceImpl.query方法耗時0毫秒
新增用戶
執行com.lnjecit.chapter4.user.UserServiceImpl.save方法耗時1毫秒

 

 

參考資料:

1、 https://blog.csdn.net/javazejian/article/details/56267036

2、 《架構探險 從零開始寫javaweb框架》


免責聲明!

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



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