這篇文章給大家分享的是有關(guān)SpringAOP在web應(yīng)用中怎么用的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
創(chuàng)新互聯(lián)-云計(jì)算及IDC服務(wù)提供商,涵蓋公有云、IDC機(jī)房租用、達(dá)州托管服務(wù)器、等保安全、私有云建設(shè)等企業(yè)級(jí)互聯(lián)網(wǎng)基礎(chǔ)服務(wù),歡迎聯(lián)系:028-86922220
一、以聲明的方式配置AOP(就是使用xml配置文件)
1.使用ProxyFactoryBean的方式:
ProxyFactoryBean類是FactoryBean的一個(gè)實(shí)現(xiàn)類,它允許指定一個(gè)bean作為目標(biāo),并且為該bean提供一組通知和顧問(wèn)(這些通知和顧問(wèn)最終會(huì)被合并到一個(gè)AOP代理中)它和我們之前的ProxyFactory都是Advised的實(shí)現(xiàn)。
以下是一個(gè)簡(jiǎn)單的例子:一個(gè)學(xué)生和一個(gè)老師,老師會(huì)告訴學(xué)生應(yīng)該做什么。
public class Student { public void talk() { System.out.println("I am a boy"); } public void walk() { System.out.println("I am walking"); } public void sleep() { System.out.println("I want to sleep"); }}
老師類
public class Teacher { private Student student; public void tellStudent(){ student.sleep(); student.talk(); } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; }}
我們創(chuàng)建一個(gè)通知類,這個(gè)和之前是一樣的SpringAOP中的通知類型以及創(chuàng)建
package cn.lyn4ever.aop;import org.aspectj.lang.JoinPoint;public class AuditAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable { System.out.println("這個(gè)方法被通知了" + method.getName()); }}
然后就使用spring的IOC來(lái)管理這個(gè)通知類,在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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> <!--注入student--> <bean name="student" class="cn.lyn4ever.aop.aopconfig.Student"> </bean> <!--注入teacher--> <bean name="teacher" class="cn.lyn4ever.aop.aopconfig.Teacher"> <!--注意,這個(gè)student的屬性要是上邊的代理類,而不是能student--> <!--<property name="student" ref="student"/>--> <property name="student" ref="proxyOne"/> </bean> <!--注入我們創(chuàng)建的通知類--> <bean id="advice" class="cn.lyn4ever.aop.aopconfig.AuditAdvice"></bean> <!--創(chuàng)建代理類,使用前邊寫(xiě)的通知進(jìn)行通知,這樣會(huì)使這個(gè)類上的所有方法都被通知--> <bean name="proxyOne" class="org.springframework.aop.framework.ProxyFactoryBean" p:target-ref="student" p:interceptorNames-ref="interceptorNames"> <!--因?yàn)閕nterceptorNames的屬性是一個(gè)可變參數(shù),也就是一個(gè)list--> </bean> <!--在上邊引入了util的名稱空間,簡(jiǎn)化了書(shū)寫(xiě)--> <util:list id="interceptorNames"> <value>advice</value> </util:list></beans>
測(cè)試類
public static void main(String[] args) { GenericXmlApplicationContext context = new GenericXmlApplicationContext(); context.load("application1.xml"); context.refresh(); Teacher teacher = (Teacher) context.getBean("teacherOne"); teacher.tellStudent(); }
運(yùn)行結(jié)果沒(méi)有問(wèn)題
以上是通過(guò)直接創(chuàng)建通知的方式,接下來(lái)我們?cè)囈粋€(gè)創(chuàng)建一個(gè)切入點(diǎn)(因?yàn)橐陨鲜菍?duì)類中所有方法都進(jìn)行通知,這時(shí)我們使用切入點(diǎn)只對(duì)其中部分方法進(jìn)行通知),在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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> <!--注入student--> <bean name="student" class="cn.lyn4ever.aop.aopconfig.Student"> </bean> <!--注入teacher--> <bean name="teacherOne" class="cn.lyn4ever.aop.aopconfig.Teacher"> <!--注意,這個(gè)student的屬性要是上邊的代理類,而不是能student--> <!--<property name="student" ref="student"/>--> <property name="student" ref="proxyOne"/> </bean> <!--注入我們創(chuàng)建的通知類--> <bean id="advice" class="cn.lyn4ever.aop.aopconfig.AuditAdvice"></bean> <!--創(chuàng)建代理類,使用前邊寫(xiě)的通知進(jìn)行通知,這樣會(huì)使這個(gè)類上的所有方法都被通知--> <bean name="proxyOne" class="org.springframework.aop.framework.ProxyFactoryBean" p:target-ref="student" p:interceptorNames-ref="interceptorNames"> <!--因?yàn)閕nterceptorNames的屬性是一個(gè)可變參數(shù),也就是一個(gè)list--> </bean> <!--在上邊引入了util的名稱空間,簡(jiǎn)化了書(shū)寫(xiě)--> <util:list id="interceptorNames"> <value>advice</value> </util:list> <!--以下是使用切入點(diǎn)的方式來(lái)進(jìn)行通知,上邊的代碼和上一個(gè)配置文件一樣,沒(méi)有修改--> <!--sutdent基本bean,我們繼續(xù)使用--> <bean name="teacherTwo" p:student-ref="proxyTwo" class="cn.lyn4ever.aop.aopconfig.Teacher"/> <bean id="proxyTwo" class="org.springframework.aop.framework.ProxyFactoryBean" p:target-ref="student" p:interceptorNames-ref="interceptorAdvisorNames"> </bean> <util:list id="interceptorAdvisorNames"> <value>advisor</value> </util:list> <!--配置切入點(diǎn)bean--> <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" p:advice-ref="advice"> <property name="pointcut"> <!--這個(gè)切入點(diǎn)我們用了一個(gè)匿名bean來(lái)寫(xiě)aspectJ的表達(dá)式,當(dāng)然也可以用其他的類型切入點(diǎn),這個(gè)在上邊鏈接中能看到--> <bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut" p:expression="execution(* talk*(..))"/> </property> </bean></beans>
上圖中的那個(gè)aspectj表達(dá)式寫(xiě)錯(cuò)了,在代碼中有正確的
2.使用aop名稱空間
在xml中引入如下的名稱空間,為了不被影響,我冊(cè)了其他多余的名稱空間。然后很普通地注入我們之前那三個(gè)bean
<?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 "> <!--通過(guò)普通的方式來(lái)注入三個(gè)bean--> <!--注入student--> <bean name="student" class="cn.lyn4ever.aop.aopconfig.Student"/> <!--注入teacher--> <bean name="teacherOne" class="cn.lyn4ever.aop.aopconfig.Teacher"> <property name="student" ref="student"/> </bean> <!--注入我們創(chuàng)建的通知類--> <bean id="advice" class="cn.lyn4ever.aop.proxyfactory.BeforeAdvice"/> <aop:config> <aop:pointcut id="talkExecution" expression="execution(* talk*(..))"/> <aop:aspect ref="advice"> <!--這個(gè)方法就是我們?cè)谧远x通知類中之寫(xiě)的方法--> <aop:before method="beforeSaySomething" pointcut-ref="talkExecution"/> <!--當(dāng)然,還可以配置其他通知類型--> </aop:aspect> </aop:config></beans>
在這個(gè)配置中,我們還可以配置其他類型的通知,但是這個(gè)method屬性一定要寫(xiě)我們自定義的那個(gè)通知類中的方法
在aop:pointcut中寫(xiě)expression時(shí)還支持如下語(yǔ)法:
<aop:pointcut id="talkExecution" expression="execution(* talk*(..)) and args(String) and bean(stu*)"/><!--中間的這個(gè)and表示和,也可以用or來(lái)表示或args(String) 意思是參數(shù)類型是string,也可是自定義的類,這個(gè)后邊有例子bean(stu*) 意思是bean的id是以stu開(kāi)頭的,常用的就是用bean(*Service*)來(lái)表示服務(wù)層的bean-->
3.使用@AspectJ樣式注解方式
雖然是通過(guò)注解的方式來(lái)聲明注解類,但是還是需要在xml中配置一點(diǎn)點(diǎn)內(nèi)容(通過(guò)注解的方式也可以配置,但是在springboot中要使用的話有更方便的方式)
為了方便,就只寫(xiě)了一個(gè)HighStudent,而且直接調(diào)用它的方法,不依賴于外部的teacher實(shí)例來(lái)調(diào)用
package cn.lyn4ever.aop.aspectj;import cn.lyn4ever.aop.aopconfig.Teacher;import org.springframework.stereotype.Component;/** * 聲明這是一個(gè)SpringBean,由Spring來(lái)管理它 */@Componentpublic class HighStudent { public void talk() { System.out.println("I am a boy"); } public void walk() { System.out.println("I am walking"); } /** * 這個(gè)方法添加一個(gè)teacher來(lái)做為參數(shù),為了配置后邊切入點(diǎn)中的args() * @param teacher */ public void sleep(Teacher teacher) { System.out.println("I want to sleep"); }}
創(chuàng)建切面類
package cn.lyn4ever.aop.aspectj;import cn.lyn4ever.aop.aopconfig.Teacher;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;/** * 聲明切面類,也就是包括切點(diǎn)和通知 */@Component //聲明交由spring管理@Aspect //表示這是一個(gè)切面類public class AnnotatedAdvice { /* 創(chuàng)建切入點(diǎn),當(dāng)然也可以是多個(gè) */ @Pointcut("execution(* talk*(..))") public void talkExecution(){} @Pointcut("bean(high*)")//這里為什么是high,因?yàn)槲覀冞@回測(cè)試bean是highStudent public void beanPoint(){} @Pointcut("args(value)") public void argsPoint(Teacher value){} /* 創(chuàng)建通知,當(dāng)然也可以是多個(gè) 這個(gè)注解的參數(shù)就是上邊的切入點(diǎn)方法名,注意有的還帶參數(shù) 這個(gè)通知方法的參數(shù)和之前一樣,榀加JoinPoint,也可不加 */ @Before("talkExecution()") public void doSomethingBefore(JoinPoint joinPoint){ System.out.println("before: Do Something"+joinPoint.getSignature().getName()+"()"); } /** * 環(huán)繞通知請(qǐng)加上ProceedingJoinPoint參數(shù) ,它是joinPoint的子類 * 因?yàn)槟阋判蟹椒ǖ脑?必須要加這個(gè) * @param joinPoint * @param teacher */ @Around("argsPoint(teacher) && beanPoint()") public Object doSomethindAround(ProceedingJoinPoint joinPoint, Teacher teacher) throws Throwable { System.out.println("Around: Before Do Something"+joinPoint.getSignature().getName()+"()"); Object proceed = joinPoint.proceed(); System.out.println("Around: After Do Something"+joinPoint.getSignature().getName()+"()"); return proceed; }}
xml中配置開(kāi)啟掃描注解
<?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" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--通知Spring掃描@Aspect注解--> <aop:aspectj-autoproxy/> <!--配置掃描包,掃描@Component--> <context:component-scan base-package="cn.lyn4ever.aop.aspectj"/></beans>
使用Java注解配置的方式配置掃描注解
@Configuration //聲明這是一個(gè)配置類@ComponentScan("cn.lyn4ever.aop.aspectj")@EnableAspectJAutoProxy(proxyTargetClass = true)//相當(dāng)于xml中的<aop:aspectj-autoproxy/>public class BeanConfig {}
測(cè)試方法
package cn.lyn4ever.aop.aspectj;import cn.lyn4ever.aop.aopconfig.Teacher;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.GenericApplicationContext;import org.springframework.context.support.GenericXmlApplicationContext;public class AspectMain { public static void main(String[] args) {// xmlConfig(); javaConfig(); } private static void javaConfig() { GenericApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); HighStudent student = (HighStudent) context.getBean("highStudent"); student.sleep(new Teacher());//應(yīng)該被環(huán)繞通知 System.out.println(); student.talk();//前置通知 System.out.println(); student.walk();//不會(huì)被通知 System.out.println(); } private static void xmlConfig(){ GenericXmlApplicationContext context = new GenericXmlApplicationContext(); context.load("application_aspect.xml"); context.refresh(); HighStudent student = (HighStudent) context.getBean("highStudent"); student.sleep(new Teacher());//應(yīng)該被環(huán)繞通知 System.out.println(); student.talk();//前置通知 System.out.println(); student.walk();//不會(huì)被通知 System.out.println(); }}
感謝各位的閱讀!關(guān)于“SpringAOP在web應(yīng)用中怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
文章標(biāo)題:SpringAOP在web應(yīng)用中怎么用
分享網(wǎng)址:http://jinyejixie.com/article14/jjejge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、做網(wǎng)站、全網(wǎng)營(yíng)銷(xiāo)推廣、云服務(wù)器、網(wǎng)站策劃、移動(dòng)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)