02_Spring

今天內容介紹

  1. Spring框架的IOC基于注解的方式
  • 注解類型
  • 注解生命周期
  1. Spring框架整合JUnit單元測試
  2. AOP的概述
  3. AOP的底層實現(xiàn)原理(了解)
  4. 動態(tài)代理
  • JDK實現(xiàn)的動態(tài)代理
  • CGLIB實現(xiàn)的動態(tài)代理
  • AspectJ的配置文件方式

技術分析之Spring框架的IOC功能之注解的方式


Spring框架的IOC之注解方式的快速入門
1, 步驟一:導入注解開發(fā)所有需要的jar包

  • 引入IOC容器必須的6個jar包
  • 多引入一個:Spring框架的AOP的jar包,spring-aop的jar包

2, 步驟二:創(chuàng)建對應的包結構,編寫Java的類

  • UserService -- 接口
  • UserServiceImpl -- 具體的實現(xiàn)類
package com.huachao.demo1;
public interface UserService {
    public void sayHello();
}
package com.huachao.demo1;
import org.springframework.stereotype.Component;
/**
 * 組件注解,標記類@Component(value="userService")等價于
 * <bean id="userService" class="com.huachao.demo1.UserServiceImp"/>
 */
@Component(value="userService")
public class UserServiceImp implements UserService {
    @Override
    public void sayHello() {
        System.out.println("Spring Hello!!");
    }
}

3, 步驟三:在src的目錄下,創(chuàng)建applicationContext.xml的配置文件,然后引入約束。注意:因為現(xiàn)在想使用注解的方式,那么引入的約束發(fā)生了變化

  • 需要引入context的約束,參考spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html40.2.8 the context schema
 <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"> <!-- bean definitions here -->
 
 </beans>

4, 步驟四:在applicationContext.xml配置文件中開啟組件掃描

  • Spring的注解開發(fā):組件掃描
    <context:component-scan base-package="com.huachao.demo1"/>

  • 注意:可以采用如下配置
    <context:component-scan base-package="com.huachao"/> 這樣是掃描com.huachao包下所有的內容

  • 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: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 definitions here -->
    <!-- 開啟注解掃描 -->
    <context:component-scan base-package="com.huachao.demo1"/>
    <!-- 也可以<context:component-scan base-package="com.huachao"/> -->
</beans>

5, 步驟五:在UserServiceImpl的實現(xiàn)類上添加注解

  • @Component(value="userService") -- 相當于在XML的配置方式中 <bean id="userService" class="...">

6, 步驟六:編寫測試代碼

@Test
    public void Run1()
    {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService us = (UserService) ac.getBean("userService");
        us.sayHello();
    }

<font color=red>注意:</font>
1,在資料/applicationContext.xml文件中,提供了spring中所有的約束


Spring框架中Bean管理的常用注解
1, @Component:組件.(作用在類上)

2, Spring中提供@Component的三個衍生注解:(功能目前來講是一致的)

  • @Controller    -- 作用在WEB層

  • @Service     -- 作用在業(yè)務層

  • @Repository    -- 作用在持久層

  • 說明:這三個注解是為了讓標注類本身的用途清晰,Spring在后續(xù)版本會對其增強

3, 屬性注入的注解(說明:使用注解注入的方式,可以不用提供set方法)

  • 如果是注入的普通類型,可以使用value注解

  • @Value -- 用于注入普通類型

  • 如果注入的是對象類型,使用如下注解

  • @Autowired -- 默認按類型進行自動裝配
      - 如果想按名稱注入
      - @Qualifier -- 強制使用名稱注入

  • @Resource -- 相當于@Autowired和@Qualifier一起使用
      -強調:Java提供的注解
     ?。?屬性使用name屬性


    @Value("美美")
    private String name;
    //@Autowired會自動尋找UserDao或其實現(xiàn)類注入
    @Autowired
    //Qualifier按名次注入
    @Qualifier(value="userDao")
    private UserDao userDao;

    //這是Java注解,Spring框架也提供支持
    @Resource(name="userDao")
    private UserDao userDao;

Bean的作用范圍和生命周期的注解
1, Bean的作用范圍注解

  • 注解為@Scope(value="prototype"),作用在類上。值如下:
  • singleton   -- 單例,默認值
  • prototype   -- 多例

2, Bean的生命周期的配置(了解)

  • 注解如下:
  • @PostConstruct  -- 相當于init-method
  • @PreDestroy   -- 相當于destroy-method

Spring框架整合JUnit單元測試
1, 為了簡化了JUnit的測試,使用Spring框架也可以整合測試
2, 具體步驟

  • 要求:必須先有JUnit的環(huán)境(即已經(jīng)導入了JUnit4的開發(fā)環(huán)境)?。?/li>
  • 步驟一:在程序中引入:spring-test.jar(Spring提供,在 spring-framework-4.2.4.RELEASE\libs\spring-test-4.2.4.RELEASE.jar)
  • 步驟二:在具體的測試類上添加注解
package com.huachao.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
    @Resource(name="userService")
    private UserService userService;
    @Test
    public void Run1()
    {
        userService.sayHello();
    }
}

需求分析

  • 使用AOP技術對DAO層操作進行增強功能

技術分析之Spring框架的核心功能之AOP技術


AOP的概述

  1. 什么是AOP的技術?
  • 在軟件業(yè),AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程
  • AOP是一種編程范式,隸屬于軟工范疇,指導開發(fā)者如何組織程序結構
  • AOP最早由AOP聯(lián)盟的組織提出的,制定了一套規(guī)范.Spring將AOP思想引入到框架中,必須遵守AOP聯(lián)盟的規(guī)范
  • 通過預編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術
  • AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內容,是函數(shù)式編程的一種衍生范型
  • 利用AOP可以對業(yè)務邏輯的各個部分進行隔離,從而使得業(yè)務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率
  1. AOP:面向切面編程.(思想.---解決OOP遇到一些問題)

  2. AOP采取橫向抽取機制,取代了傳統(tǒng)縱向繼承體系重復性代碼(性能監(jiān)視、事務管理、安全檢查、緩存)

  3. 為什么要學習AOP

  • 可以在不修改源代碼的前提下,對程序進行增強??!

Spring框架的AOP的底層實現(xiàn)
1, Srping框架的AOP技術底層也是采用的代理技術,代理的方式提供了兩種

  • 基于JDK的動態(tài)代理
  • 必須是面向接口的,只有實現(xiàn)了具體接口的類才能生成代理對象

2, 基于CGLIB動態(tài)代理

  • 對于沒有實現(xiàn)了接口的類,也可以產(chǎn)生代理,產(chǎn)生這個類的子類的方式

3, Spring的傳統(tǒng)AOP中根據(jù)類是否實現(xiàn)接口,來采用不同的代理方式

  • 如果實現(xiàn)類接口,使用JDK動態(tài)代理完成AOP
  • 如果沒有實現(xiàn)接口,采用CGLIB動態(tài)代理完成AOP

JDK的動態(tài)代理(代碼了解,理解原理)

  • 使用Proxy類來生成代理對象的一些代碼如下:
 /**
  * 使用JDK的方式生成代理對象
  * @author Administrator
  */
 public class MyProxyUtils {
 public static UserDao getProxy(final UserDao dao) {
 // 使用Proxy類生成代理對象
 UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
 dao.getClass().getInterfaces(), new InvocationHandler() {
 
 // 代理對象方法一直線,invoke方法就會執(zhí)行一次
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if("save".equals(method.getName())){
 System.out.println("記錄日志...");
 // 開啟事務
 }
 // 提交事務
 // 讓dao類的save或者update方法正常的執(zhí)行下去
 return method.invoke(dao, args);
 }
 });
 // 返回代理對象
 return proxy;
 }
 }

例:JDK的動態(tài)代理的使用
UserDao接口

package com.huachao.demo2;
public interface UserDao {
    public void save();
    public void update();
}

接口實現(xiàn)類

package com.huachao.demo2;
public class UserDaoImp implements UserDao {
    @Override
    public void save() {
        System.out.println("保存...");
    }
    @Override
    public void update() {
        System.out.println("更新...");
    }
}

動態(tài)代理的工具類

package com.huachao.demo2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxyUtil {
    public static UserDao getProxy(final UserDao dao){
        UserDao proxy =(UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), 
                dao.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if("save".equals(method.getName()))
                        {
                            System.out.println("記錄日志");
                        }
                        return method.invoke(dao, args);
                    }
                });
        return proxy;
    }
}

測試代碼

    @Test
    public void Run1()
    {
        UserDao dao = new UserDaoImp();
        
        UserDao proxy = MyProxyUtil.getProxy(dao);
        proxy.save();
        proxy.update();
    }

CGLIB的代理技術(代碼了解)

  1. 引入CBLIB的開發(fā)包
  • 如果想使用CGLIB的技術來生成代理對象,那么需要引入CGLIB的開發(fā)的jar包,在Spring框架核心包中已經(jīng)引入了CGLIB的開發(fā)包了。所以直接引入Spring核心開發(fā)包即可!
  1. 編寫相關的代碼
 public static OrderDaoImpl getProxy(){
 // 創(chuàng)建CGLIB核心的類
 Enhancer enhancer = new Enhancer();
 // 設置父類
 enhancer.setSuperclass(OrderDaoImpl.class);
 // 設置回調函數(shù)
 enhancer.setCallback(new MethodInterceptor() {
 @Override
 public Object intercept(Object obj, Method method, Object[] args,
 MethodProxy methodProxy) throws Throwable {
 if("save".equals(method.getName())){
 // 記錄日志
 System.out.println("記錄日志了...");
 }
 return methodProxy.invokeSuper(obj, args);
 }
 });
 // 生成代理對象
 OrderDaoImpl proxy = (OrderDaoImpl) enhancer.create();
 return proxy;
 }

例:使用Spring核心包提供的CGLib動態(tài)代理技術
繼續(xù)使用上例的接口和實現(xiàn)類
CGLib的工具類

package com.huachao.demo2;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class MyCGLibUtils {
    public static UserDao getProxy(){
        Enhancer enhancer = new Enhancer();
        //設置父類
        enhancer.setSuperclass(UserDaoImp.class);
        //設置回調函數(shù)
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if("save".equals(method.getName()))
                {
                    System.out.println("記錄日志");
                }
                //讓方法正常執(zhí)行
                return methodProxy.invokeSuper(obj, args);
            }
        });
        
        UserDao dao = (UserDao) enhancer.create();
        return dao;
    }
}

測試代碼


    @Test
    public void Run2()
    {
        UserDao proxy = MyCGLibUtils.getProxy();
        proxy.save();
        proxy.update();
    }

注意:上例不使用接口也能生成動態(tài)代理對象


Spring基于AspectJ的AOP的開發(fā)


技術分析之AOP的相關術語

  1. Joinpoint(連接點)  -- 所謂連接點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支持方法類型的連接點
  2. Pointcut(切入點)   -- 所謂切入點是指我們要對哪些Joinpoint進行攔截的定義
  3. Advice(通知/增強)  -- 所謂通知是指攔截到Joinpoint之后所要做的事情就是通知.通知分為前置通知,后置通知,異常通知,最終通知,環(huán)繞通知(切面要完成的功能)
  4. Introduction(引介)  -- 引介是一種特殊的通知在不修改類代碼的前提下, Introduction可以在運行期為類動態(tài)地添加一些方法或Field
  5. Target(目標對象)   -- 代理的目標對象
  6. Weaving(織入)   -- 是指把增強應用到目標對象來創(chuàng)建新的代理對象的過程
  7. Proxy(代理)   -- 一個類被AOP織入增強后,就產(chǎn)生一個結果代理類
  8. Aspect(切面)    -- 是切入點和通知的結合,以后咱們自己來編寫和配置的

技術分析之AspectJ的XML方式完成AOP的開發(fā)
1, 步驟一:創(chuàng)建JavaWEB項目,引入具體的開發(fā)的jar包

  • 先引入Spring框架開發(fā)的基本開發(fā)包

  • 再引入Spring框架的AOP的開發(fā)包

  • spring的傳統(tǒng)AOP的開發(fā)的包
     ?。?code>spring-aop-4.2.4.RELEASE.jar(Spring的AOP包)
     ?。?com.springsource.org.aopalliance-1.0.0.jar(AOP聯(lián)盟的規(guī)范包)

  • aspectJ的開發(fā)包
     ?。?code>com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar(aspectJ的包)
      -spring-aspects-4.2.4.RELEASE.jar(Spring整合aspectJ的包)

2, 步驟二:創(chuàng)建Spring的配置文件,引入具體的AOP的schema約束
參考spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html中的40.2.7 the aop schema


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

3, 步驟三:創(chuàng)建包結構,編寫具體的接口和實現(xiàn)類

  • com.itheima.demo1
  • CustomerDao -- 接口
  • CustomerDaoImpl -- 實現(xiàn)類

4, 步驟四:將目標類配置到Spring中
  <bean id="customerDao" class="com.itheima.demo3.CustomerDaoImpl"/>

5, 步驟五:定義切面類


 public class MyAspectXml {
 // 定義通知
 public void log(){
 System.out.println("記錄日志...");
 }
 }

6, 步驟六:在配置文件中定義切面類
  <bean id="myAspectXml" class="com.itheima.demo3.MyAspectXml"/>

7, 步驟七:在配置文件中完成aop的配置

 <aop:config>
 <!-- 引入切面類 -->
 <aop:aspect ref="myAspectXml">
 <!-- 定義通知類型:切面類的方法和切入點的表達式 -->
 <aop:before method="log" pointcut="execution(public * com.itheima.demo3.CustomerDaoImpl.save(..))"/>
 </aop:aspect>
 </aop:config>

8, 完成測試


 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:applicationContext.xml")
 public class Demo3 {
 @Resource(name="customerDao")
 private CustomerDao customerDao;
 @Test
 public void run1(){
 customerDao.save();
 customerDao.update();
 customerDao.delete();
 }
 }

例:使用aspectJ實現(xiàn)動態(tài)代理

  1. 新建項目,本例命名為day36_aop

  2. 導包,參考上面的步驟,本例導入的所有包如下:
    com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.apache.commons.logging-1.1.1.jar com.springsource.org.apache.log4j-1.2.15.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar spring-aop-4.2.4.RELEASE.jar spring-aspects-4.2.4.RELEASE.jar spring-beans-4.2.4.RELEASE.jar spring-context-4.2.4.RELEASE.jar spring-core-4.2.4.RELEASE.jar spring-expression-4.2.4.RELEASE.jar spring-test-4.2.4.RELEASE.jar

  3. 導入log4j.properties到src目錄下

  4. 在src目錄下,新建applicationContext.xml,約束參考上面步驟

  5. 編寫接口和顯示類

package com.huachao.demo1;
public interface CustomerDao {
    public void save();
    public void update();
}
package com.huachao.demo1;
public class CustomerDaoImp implements CustomerDao {
    @Override
    public void save() {
        System.out.println("save");
    }
    @Override
    public void update() {
        System.out.println("update");
    }
}

定義切面類

package com.huachao.demo1;

public class MyAspectJXml {
    public void log()
    {
        System.out.println("記錄日志...");
    }
}

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 -->
    
    <bean id="customerDao" class="com.huachao.demo1.CustomerDaoImp"/>
    <bean id="myAspectJXml" class="com.huachao.demo1.MyAspectJXml"/>
    
    <aop:config>
        <!-- 引入切面 -->
        <aop:aspect ref="myAspectJXml">
            <!-- 定義通知類型:切面類的方法和切入點的表達式 -->
            <!-- 切入點的表達式 
                1. execution()    固定的,不能不寫
                2. public 可以省略不寫
                3. void,返回值可以出現(xiàn) * 表示任意的返回值,返回值類型不能不寫
                4. 可以使用 * 代替的,不能不編寫的,簡寫方式:*..*方法
                5. *DaoImpl
                6. 方法 save*
                7. 方法的參數(shù):
            -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.demo1.CustomerDaoImp.save(..))"/> -->
            <aop:before method="log" pointcut="execution(public * com.huachao.demo1.CustomerDaoImp.save())"/>
        </aop:aspect>
    </aop:config>
</beans>

測試代碼

package com.huachao.demo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
    @Resource(name="customerDao")
    private CustomerDao customerDao;
    
    @Test
    public void Run1()
    {
        customerDao.save();
        customerDao.update();
    }
}

切入點的表達式
1,再配置切入點的時候,需要定義表達式,重點的格式如下:execution(public * *(..)),具體展開如下:

  • 切入點表達式的格式如下:

  • execution([修飾符] 返回值類型 包名.類名.方法名(參數(shù)))

  • 修飾符可以省略不寫,不是必須要出現(xiàn)的。

  • 返回值類型是不能省略不寫的,根據(jù)你的方法來編寫返回值。可以使用 * 代替。

  • 包名例如:com.itheima.demo3.BookDaoImpl

  • 首先com是不能省略不寫的,但是可以使用 * 代替

  • 中間的包名可以使用 * 號代替

  • 如果想省略中間的包名可以使用 ..

  • 類名也可以使用 * 號代替,也有類似的寫法:*DaoImpl

  • 方法也可以使用 * 號代替

  • 參數(shù)如果是一個參數(shù)可以使用 * 號代替,如果想代表任意參數(shù)使用 ..

例:切點的幾種寫法
切入點的表達式:

  1. execution() 固定的,不能不寫
  2. public 可以省略不寫
  3. void,返回值可以出現(xiàn) * 表示任意的返回值,返回值類型不能不寫
  4. 包名:可以使用 * 代替的,不能不編寫的,可以簡寫方式:..方法
  5. 類名:*DaoImpl
  6. 方法 save*
  7. 方法的參數(shù):一個*表示一個參數(shù),..表示任意的參數(shù),相當于可變參數(shù)

            <!-- <aop:before method="log" pointcut="execution(public void com.huachao.demo1.CustomerDaoImp.save())"/> -->
            <!-- <aop:before method="log" pointcut="execution(void com.huachao.demo1.CustomerDaoImp.save())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.demo1.CustomerDaoImp.save())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.*.CustomerDaoImp.save())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* *..*.CustomerDaoImp.save())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.demo1.*DaoImp.save())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.demo1.CustomerDaoImp.save*())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.demo1.CustomerDaoImp.*())"/> -->
            <!-- <aop:before method="log" pointcut="execution(* com.huachao.demo1.CustomerDaoImp.save(..))"/> -->

AOP的通知類型
1, 前置通知

  • 在目標類的方法執(zhí)行之前執(zhí)行。
  • 配置文件信息:<aop:after method="before" pointcut-ref="myPointcut3"/>
  • 應用:可以對方法的參數(shù)來做校驗

2, 最終通知

  • 在目標類的方法執(zhí)行之后執(zhí)行,如果程序出現(xiàn)了異常,最終通知也會執(zhí)行。
  • 在配置文件中編寫具體的配置:<aop:after method="after" pointcut-ref="myPointcut3"/>
  • 應用:例如像釋放資源

3, 后置通知

  • 方法正常執(zhí)行后的通知。
  • 在配置文件中編寫具體的配置:<aop:after-returning method="afterReturning" pointcut-ref="myPointcut2"/>
  • 應用:可以修改方法的返回值

4, 異常拋出通知

  • 在拋出異常后通知
  • 在配置文件中編寫具體的配置:<aop:after-throwing method="afterThorwing" pointcut-ref="myPointcut3"/>
  • 應用:包裝異常的信息

5, 環(huán)繞通知

  • 方法的執(zhí)行前后執(zhí)行。
  • 在配置文件中編寫具體的配置:<aop:around method="around" pointcut-ref="myPointcut2"/>
  • 要注意:目標的方法默認不執(zhí)行,需要使用ProceedingJoinPoint對來讓目標對象的方法執(zhí)行。
/**
  * 環(huán)繞通知:方法執(zhí)行之前和方法執(zhí)行之后進行通知,默認的情況下,目標對象的方法不能執(zhí)行的。需要手動讓目標對象的方法執(zhí)行
  */
 public void around(ProceedingJoinPoint joinPoint){
 System.out.println("環(huán)繞通知1...");
 try {
 // 手動讓目標對象的方法去執(zhí)行
 joinPoint.proceed();
 } catch (Throwable e) {
 e.printStackTrace();
 }
 System.out.println("環(huán)繞通知2...");
 }

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容