重新認識AOP(一)

      我們知道springframework的核心是IOC和AOP,通過AOP可以輕鬆實現諸如日誌,事物,監控等功能,我們最近在做數據庫歸檔技改也用到了AOP切面,spring aop提供了下面一些註解,比如@Before,@Around,@After @AfterReturning @AfterThrowing,這些註釋參考官網文檔即可https://docs.spring.io/spring/docs/5.2.5.RELEASE/spring-framework-reference/core.html#spring-core

      Spring AOP includes the following types of advice:

  • Before advice: Advice that runs before a join point but that does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).
  • After returning advice: Advice to be run after a join point completes normally (for example, if a method returns without throwing an exception).
  • After throwing advice: Advice to be executed if a method exits by throwing an exception.
  • After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).
  • Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

     重點解釋下around,從字面意思環繞的意思,好像是執行目標方法的先進入around方法,然後執行目標方法,然後再回調around方法(如果around方法沒有執行pjp.proceed(pjp.getArgs())),其實不是這樣的,官網的意思應該是我們通過Around advice可以做一些事情的機會,比如啥時候做,怎麼去執行目標方法,或者乾脆不執行目標方法, 如果你在around裏不執行pjp.proceed(不執行這個不會執行@Before註解),而是調用別的接口直接return也是可以的。

  測試代碼如下:

public interface TestAspectService {
    String getNameInfo(String name);
}


public class TestAspectServiceImpl implements TestAspectService {

    private String dataSource;

    @Override
    public String getNameInfo(String param) {
        System.out.println("dataSource"+dataSource);
        System.out.println("param"+param);
        return param;
    }

    public String getDataSource() {
        return dataSource;
    }

    public void setDataSource(String dataSource) {
        this.dataSource = dataSource;
    }
}

@Aspect
@Component
public class TestIntercept {

    @Resource
    private TestAspectService mainDbarchiveDb;


    @Pointcut("execution(public * com.jd.order.shop.service.TestAspectServiceImpl.getNameInfo(..)) && bean(mainDb)")
    public void aspectInfo(){}


    @Before("aspectInfo()")
    public void before() {
        this.printInfo("@Before 開始打印日誌");
    }


    @Around("aspectInfo()")
    public Object doGetPopOrderDataListByOrderIds(ProceedingJoinPoint pjp) throws Throwable {
       System.out.println("around開始");
        pjp.proceed(pjp.getArgs());
        System.out.println("around結束");
        return mainDbarchiveDb.getNameInfo("testguidang");
    }

    @After("aspectInfo()")
    public void after() {
        this.printInfo("@After 已經執行完成");
    }


    private void printInfo(String info){
        System.out.println(info);
    }
}

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AppStart.class)
public class TestInterceptDemo {
    @Resource
    private TestAspectService mainDb;

    @Test
    public void testInfo() {
        System.out.println(mainDb.getNameInfo("主庫信息"));

    }


}


  <aop:aspectj-autoproxy proxy-target-class="true"/>
    <bean id="mainDb" name="mainDb" class="com.jd.order.shop.service.TestAspectServiceImpl">
        <property name="dataSource" value="mainDb" />
    </bean>

    <bean id="mainDbarchiveDb" name="mainDbarchiveDb" class="com.jd.order.shop.service.TestAspectServiceImpl">
        <property name="dataSource" value="archiveDb" />
    </bean>

測試結果如下:自己可以根據測試用例做調整

Security framework of XStream not initialized, XStream is probably vulnerable.
around開始
@Before 開始打印日誌
dataSourcemainDb
param主庫信息
around結束
dataSourcearchiveDb
paramtestguidang
@After 已經執行完成
testguidang

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章