1. 程式人生 > >Spring AOP如何讓內部方法呼叫也發生代理

Spring AOP如何讓內部方法呼叫也發生代理

方法之間的呼叫直接使用的是原始物件,而非代理物件,因而內部呼叫不會產生代理

public class Waiter {
    public void greetTo(String name) {
        System.out.println("greet to :" + name);
    }

    public void serveTo(String name) {
        System.out.println("serve to :" + name);
        greetTo(name);
    }
public class Seller {
    public void greetTo(String name) {
        System.out.println("greet to :" + name);
    }
}
    <bean id="waiter" class="com.demo.aop.Waiter"/>
    <bean id="seller" class="com.demo.aop.Seller"/>
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
          p:patterns=".*To.*">
        <property name="advice">
            <bean class="com.demo.aop.GreetingAdvice"/>
        </property>
    </bean>
    <!--自動根據advisor生成代理-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          p:proxyTargetClass="true"/>

測試類:

@ContextConfiguration(locations = {"classpath:spring-context.xml"})
public class Test extends AbstractJUnit4SpringContextTests {
    @org.junit.Test
    public void test1() {
        Waiter waiter = (Waiter) applicationContext.getBean("waiter");
        Seller seller = (Seller) applicationContext.getBean("seller");
        System.out.println("---------------------------");
        waiter.greetTo("John");
        System.out.println("---------------------------");
        waiter.serveTo("Ivern");
        System.out.println("---------------------------");
        seller.greetTo("Lili");
    }
}

結果:greet方法的內部呼叫沒有生成代理


修改:

/**
 * 自動裝配代理物件介面
 */
public interface BeanSelfProxyAware {
    void setBeanSelfProxy(Object proxyObj);
}
/**
 * 自定義容器啟動外掛
 */
public interface SystemBootAddon extends Ordered {
    void onReady();
}
/**
 * 自定義管理器,當啟動完成時,對實現了BeanSelfProxyAware介面的bean注入proxyBean
 */
public class BeanSelfProxyMonter implements ApplicationContextAware, SystemBootAddon {
    private ApplicationContext applicationContext;

    public void onReady() {
        Map<String, BeanSelfProxyAware> proxyAwares = applicationContext.getBeansOfType(BeanSelfProxyAware.class);
        for (BeanSelfProxyAware proxyAware : proxyAwares.values()) {
            proxyAware.setBeanSelfProxy(proxyAware);
        }
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}
/**
 * 訊息監聽器,監聽Spring系統訊息
 */
public class SystemBootManager implements ApplicationListener<ContextRefreshedEvent> {
    private List<SystemBootAddon> systemBootAddons;
    private boolean hasRunOnce = false;

    /**
     * Spring自動注入所有的SystemBootAddon
     *
     * @param systemBootAddons
     */
    @Autowired
    public void setSystemBootAddons(List<SystemBootAddon> systemBootAddons) {
        this.systemBootAddons = systemBootAddons;
    }

    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        if (!hasRunOnce) {
            for (SystemBootAddon systemBootAddon :systemBootAddons) {
                systemBootAddon.onReady();
            }
            hasRunOnce = true;
        }
    }
}
<bean id="waiter" class="com.demo.aop.Waiter"/>
    <bean id="seller" class="com.demo.aop.Seller"/>
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
          p:patterns=".*To.*">
        <property name="advice">
            <bean class="com.demo.aop.GreetingAdvice"/>
        </property>
    </bean>
    <!--自動根據advisor生成代理-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          p:proxyTargetClass="true"/>
    <!--註冊啟動器-->
    <bean class="com.demo.aop.BeanSelfProxyMonter"/>
    <!--註冊啟動載入器-->
    <bean class="com.demo.aop.SystemBootManager"/>
public class Waiter implements BeanSelfProxyAware {
    private Waiter waiterProxy;

    public void setBeanSelfProxy(Object proxyObj) {
        this.waiterProxy = (Waiter) proxyObj;
    }

    public void greetTo(String name) {
        System.out.println("greet to :" + name);
    }

    public void serveTo(String name) {
        System.out.println("serve to :" + name);
        waiterProxy.greetTo(name);
    }
}

最後的結果:







相關推薦

Spring AOP如何內部方法呼叫發生代理

方法之間的呼叫直接使用的是原始物件,而非代理物件,因而內部呼叫不會產生代理public class Waiter { public void greetTo(String name) { System.out.println("greet to :"

spring AOP中自身方法呼叫無法應用代理解決辦法

如下例: public class MyServiceImpl implements MyService { public void do(){ //the transaction annotation won't work if yo

spring aop內部呼叫不攔截原因及解決方案

       spring對應java web開發的同學來說,都不陌生,其中事務@Transactional在service層更是常常使用。 1.aop類內部呼叫不攔截原因 細心的同學也許早就發現當service中的某個沒標註@Transactional的方法呼叫另一個標註

Spring AOP獲取攔截方法的參數名稱跟參數值

mon ogg try cat obj 超過 con 同時 point Spring AOP獲取攔截方法的參數名稱跟參數值 註意:這種方式需要JDK1.8版本支持 開始: 1.aop配置: <aop:aspectj-autoproxy expose-proxy

restTemplate踩過的坑-spring clound--cloud內部服務呼叫重試次數

轉載自 https://www.cnblogs.com/jimw/p/9037542.html 現在公司專案基本都從臃腫的專案轉換成微服務的方向轉換,因此也從中使用了spring clound的一些元件,在此過程中就遇到了restTemplate的坑。 起初,是直接注入RestTe

Spring Aop 修改目標方法引數和返回值

首先使用spring-aop需要在spring的配置檔案中假如 一、新建註解 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented

Spring,為內部方法新起一個事務,此處應有坑

事務的作用,使我們操作能夠連貫起來。而spring則是提供了一個更簡單的方法,只要使用 @Transactional 一個註解,就可以保證操作的連貫性了。 普通用法,稍後再說,這裡要說的是: 在最外面的方法中,有一個@Transactional 的註解,當有丟擲異常時

Spring傳播行為內部方法不起作用

在使用Spring的註解事務時候,我們發現內部方法宣告的事務不起作用,而是決定於外部方法註解的事務。到底是真不起作用,還是我們Spring的事務註解機制理解錯了,導致誤用了。下面我們看兩個例子: 測試類: package com.aop; import org.spr

解決@Transactional事務在類內部方法呼叫不生效

UserServiceImpl測試實現類package cn.sw.study.web.service.impl;import cn.sw.study.web.dao.UserMapper;import cn.sw.study.web.model.User;import cn.sw.study.web.ser

spring AOP獲取切面方法資訊 JoinPoint的用法

JoinPoint 物件 封裝了SpringAop中切面方法的資訊,在切面方法中新增JoinPoint引數,就可以獲取到封裝該方法資訊的物件 常用api ; 方法名 功能 Signature getSignature();

Spring AOP專案應用——方法入參校驗 & 日誌橫切

應用一:方法入參校驗由於系統多個方法入參均對外封裝了統一的Dto,其中Dto中幾個必傳引數在每個方法中都會進行相同的校驗邏輯。筆者考慮採用Spring AOP進行優化,攔截方法進行引數校驗。測試case

Spring AOP 各種攔截方法執行的順序

AOPImpl.java ================== package salesdepart.service.app; import org.aspectj.lang.annotation.*; import org.aspectj.lang.*; import

spring 本類中方法呼叫另外一個方法事務不生效

1、在spring配置檔案中新增 <aop:aspectj-autoproxy expose-proxy="true"/&g

spring 同一個類中方法呼叫 註解不起作用

spring  同一個類中方法呼叫 註解不起作用 需要新增 AopContext.currentProxy() 這樣

【框架】[Spring]AOP攔截-三種方式實現自動代理

這裡的自動代理,我講的是自動代理bean物件,其實就是在xml中讓我們不用配置代理工廠,也就是不用配置class為org.springframework.aop.framework.ProxyFactoryBean的bean。 總結了一下自己目前所學的知識

Spring AOP中的JDK和CGLib動態代理哪個效率更高?

一、背景 今天有小夥伴面試的時候被問到:Spring AOP中JDK 和 CGLib動態代理哪個效率更高? 二、基本概念 首先,我們知道Spring AOP的底層實現有兩種方式:一種是JDK動態代理,另一種是CGLib的方式。 自Java 1.3以後

Spring aop利用jdk的InvocationHandler產生動態代理

筆記之用…… 首先有一個介面UserService package com.spring.test; import org.springframework.stereotype.Component; @Component public interface Use

Spring AOP簡介與底層實現機制——動態代理

AOP簡介 AOP (Aspect Oriented Programing) 稱為:面向切面程式設計,它是一種程式設計思想。AOP 是 OOP(面向物件程式設計 Object Oriented Programming)的思想延續 AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼的編寫方式(例如

spring aop無法攔截類內部方法呼叫

1.概念 攔截器的實現原理就是動態代理,實現AOP機制。Spring 的代理實現有兩種:一是基於 JDK Dynamic Proxy 技術而實現的;二是基於 CGLIB 技術而實現的。如果目標物件實現了介面,在預設情況下Spring會採用JDK的動態代理實現AOP 2.問題 在類C中,方法A呼叫方法B, B方

spring中mock RestTemplate和FeignClient(mock方法內部方法呼叫

目的 要測試ServiceImpl類中的方法methodA 難點 methodA中呼叫了restTemplate的方法或者FeignClient的方法,而這兩個方法都依賴第三方應用,如果第三方應用沒有準備好,則會報錯,為了在單元測試中不依賴第三方應用,因此需要mock他們。