Spring AOP攔截-三種方式實現(xiàn)自動代理詳解
這里的自動代理,我講的是自動代理bean對象,其實就是在xml中讓我們不用配置代理工廠,也就是不用配置class為org.springframework.aop.framework.ProxyFactoryBean的bean。
總結(jié)了一下自己目前所學的知識。
發(fā)現(xiàn)有三種方式實現(xiàn)自動代理
用Spring一個自動代理類DefaultAdvisorAutoProxyCreator:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" data-filtered="filtered"></bean>
例如:
原來不用自動代理的配置文件如下:
<!--?xml version="1.0" encoding="UTF-8"?-->
<beans xmlns="https://www.springframework.org/schema/beans" xmlns:context="https://www.springframework.org/schema/context" xmlns:tx="https://www.springframework.org/schema/tx" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.3.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 代理前原對象 -->
<bean class="cn.hncu.xmlImpl.Person" id="person"></bean>
<!-- 切面 = 切點+通知 -->
<bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor">
<!-- 切點 -->
<property name="patterns">
<list>
<value>.*run.*</value>
</list>
</property>
<!-- 通知-由我們寫,實際代理動作 -->
<property name="advice">
<bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></bean>
</property>
</bean>
<!-- 代理工廠 -->
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="personProxied">
<!-- 放入原型對象 -->
<property name="target" ref="person"></property>
<!-- 放入切面 -->
<property name="interceptorNames">
<list>
<value>advisor</value>
</list>
</property>
</bean>
</beans>
現(xiàn)在改用自動代理,如下配置:
<beans ...="">
<!-- 代理前原對象 -->
<bean class="cn.hncu.xmlImpl.Person" id="person"></bean>
<!-- 切面 = 切點+通知 -->
<bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor">
<!-- 切點 -->
<property name="patterns">
<list>
<value>.*run.*</value>
</list>
</property>
<!-- 通知-由我們寫,實際代理動作 -->
<property name="advice">
<bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></bean>
</property>
</bean>
<!-- 自動代理 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
</beans>
測試方法
@Test//自動代理
public void demo4(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/4.xml");
//我們直接在這里獲取Person對象就可以了,因為在最開始xml文件newPerson對象后,Spring就已經(jīng)幫我們代理了!
Person p =ctx.getBean(Person.class);
p.run();
p.say();
}
相對于前面,也就是把代理工廠部分換成自動代理了。
演示結(jié)果:

自己寫一個自動代理底層實現(xiàn):
我們也可以寫一個類,來實現(xiàn)DefaultAdvisorAutoProxyCreator自動代理的功能!
首先,我們需要實現(xiàn)一個接口,也就是BeanPostProcessor接口。
BeanPostProcessor接口作用是:如果我們需要在Spring容器完成Bean的實例化、配置和其他的初始化前后添加一些自己的邏輯處理,我們就可以定義一個或者多個BeanPostProcessor接口的實現(xiàn),然后注冊到容器中。
而我們想要在原型對象bean被創(chuàng)建之后就代理了,就必須在原來的容器中拿到原來的原型對象,需要拿到原來spring容器中的切面對象,這個時候,我們就需要原來的容器,這個時候就需要另一個接口,也就是ApplicationContextAware接口!
通過這2個接口,我們就可以實現(xiàn)自動代理了。
package cn.hncu.xmlImpl;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MyAutoProxy implements BeanPostProcessor,ApplicationContextAware{
private ApplicationContext applicationContext=null;
//bean創(chuàng)建之前調(diào)用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;//在這里,我們直接放行
}
//bean創(chuàng)建之后調(diào)用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
ProxyFactoryBean factory = new ProxyFactoryBean();
//把原型對象放入代理工廠
factory.setTarget(bean);
//在這里
Advisor adv = applicationContext.getBean(Advisor.class);
factory.addAdvisor(adv);
//返回被代理后的對象
return factory.getObject();
}
//拿到原來的spring中的容器
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext=applicationContext;
}
}
5.xml
<beans...>
<!-- 代理前原對象 -->
<bean class="cn.hncu.xmlImpl.Person" id="person"></bean>
<!-- 切面 = 切點+通知 -->
<bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor">
<!-- 切點 -->
<property name="patterns">
<list>
<value>.*run.*</value>
</list>
</property>
<!-- 通知-由我們寫,實際代理動作 -->
<property name="advice">
<bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></bean>
</property>
</bean>
<!-- 自己寫的自動代理 -->
<bean class="cn.hncu.xmlImpl.MyAutoProxy"></bean>
</beans...>
測試方法:
@Test//自己實現(xiàn)的自動代理
public void demo5(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/5.xml");
Person p =ctx.getBean(Person.class);
p.run();
p.say();
}
測試結(jié)果就不上圖了,和前面是一樣的。
其實很多時候,我們?nèi)绻约喝ゾ氁幌碌讓樱瑢ι蠈拥目蚣芨美斫狻?/p>
還有一種方法。
使用aop標簽配自動代理
需要在beans加一個命名空間
xmlns:aop=https://www.springframework.org/schema/aop
還需要配xsi:schemaLocation,為aop加一個網(wǎng)絡地址。
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.3.xsd
我們需要一個aspectjweaver-jar包:
xml配置文件:
<!--?xml version="1.0" encoding="UTF-8"?-->
<beans xmlns="https://www.springframework.org/schema/beans" xmlns:aop="https://www.springframework.org/schema/aop" xmlns:context="https://www.springframework.org/schema/context" xmlns:tx="https://www.springframework.org/schema/tx" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.3.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.3.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.3.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.3.xsd ">
<!-- 利用sop標簽實現(xiàn)自動代理 -->
</aop:aspectj-autoproxy>
<!-- 代理前原對象 -->
<bean class="cn.hncu.xmlImpl.Person" id="person"></bean>
<!-- 切面 = 切點+通知 -->
<bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor">
<!-- 切點 -->
<property name="patterns">
<list>
<value>.*run.*</value>
</list>
</property>
<!-- 通知-由我們寫,實際代理動作 -->
<property name="advice">
<bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></bean>
</property>
</bean>
</beans>
測試方法:
@Test//自動代理
public void demo6(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/6.xml");
Person p =ctx.getBean(Person.class);
p.run();
p.say();
}
測試結(jié)果:

個人覺得能學會使用一種就OK了,不用全部記下來,為了學習,都了解一下就好,別人寫出來,能看懂就好。
哈哈,其實底層學好了,自己寫的時候,就算不會用Spring的自動代理,自己寫出來底層也是蠻好的嘛
總結(jié)
以上本文關于Spring AOP攔截-三種方式實現(xiàn)自動代理詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:快速理解Java設計模式中的組合模式、Java編程接口調(diào)用的作用及代碼分享、淺談Java實體對象的三種狀態(tài)以及轉(zhuǎn)換關系等,有什么問題可以隨時留言,小編會及時回復大家的。感謝朋友們對本站的支持!
相關文章
Java基礎知識精通注釋與數(shù)據(jù)類型及常量與變量
本文給大家介紹了Java的注釋與數(shù)據(jù)類型和常量變量,這些都是最基礎的知識,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04
java實現(xiàn)字符串轉(zhuǎn)String數(shù)組的方法示例
這篇文章主要介紹了java實現(xiàn)字符串轉(zhuǎn)String數(shù)組的方法,涉及java字符串的遍歷、分割、轉(zhuǎn)換等相關操作技巧,需要的朋友可以參考下2017-10-10
SpringBoot?整合?Elasticsearch?實現(xiàn)海量級數(shù)據(jù)搜索功能
這篇文章主要介紹了SpringBoot?整合?Elasticsearch?實現(xiàn)海量級數(shù)據(jù)搜索,本文主要圍繞?SpringBoot?整合?ElasticSearch?接受數(shù)據(jù)的插入和搜索使用技巧,在實際的使用過程中,版本號尤其的重要,不同版本的?es,對應的?api?是不一樣,需要的朋友可以參考下2022-07-07

