演示5種方式配置文件AOP
創(chuàng)新互聯(lián)是一家專注于網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)與策劃設(shè)計(jì),圖們網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:圖們等地區(qū)。圖們做網(wǎng)站價(jià)格咨詢:13518219792
1. bean class="cn.hncu.spring4x.aop.Cat" id="cat"/bean
!-- 切點(diǎn) --
bean class="org.springframework.aop.support.JdkRegexpMethodPointcut" id="pointcut"
property name="pattern" value=".*run.*"/property
/bean
!-- 通知 ,要自己寫--
bean class="cn.hncu.spring4x.aop.AroundAdvice" id="advice"/bean
!-- 切面=切點(diǎn)+通知 --
bean class="org.springframework.aop.support.DefaultPointcutAdvisor" id="advisor"
property name="advice" ref="advice"/property
property name="pointcut" ref="pointcut"/property
/bean
bean class="org.springframework.aop.framework.ProxyFactoryBean" id="catProxide"
property name="target" ref="cat"/property
property name="interceptorNames"
list
valueadvisor/value
/list
/property
/bean
2. bean class="cn.hncu.spring4x.aop.Cat" id="cat"/bean
!-- 切面=切點(diǎn)+通知 (把切點(diǎn)和通知寫成內(nèi)部bean)--
bean class="org.springframework.aop.support.DefaultPointcutAdvisor" id="advisor"
property name="advice"
bean class="cn.hncu.spring4x.aop.AroundAdvice"/bean
/property
property name="pointcut"
bean class="org.springframework.aop.support.JdkRegexpMethodPointcut"
property name="patterns"
list
value.*run.*/value
value.*say.*/value
/list
/property
/bean
/property
/bean
bean class="org.springframework.aop.framework.ProxyFactoryBean" id="catProxide"
property name="target" ref="cat"/property
property name="interceptorNames"
list
valueadvisor/value
/list
/property
/bean
3.bean class="cn.hncu.spring4x.aop.Cat" id="cat"/bean
!--//直接在切面bean中配置“切點(diǎn)的正則表達(dá)式”,省去“切點(diǎn)bean”的配置 用到這個(gè)類 org.springframework.aop.support.RegexpMethodPointcutAdvisor --
bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor"
property name="advice"
bean class="cn.hncu.spring4x.aop.AroundAdvice"/bean
/property
property name="patterns"
list
value.*run.*/value
/list
/property
/bean
bean class="org.springframework.aop.framework.ProxyFactoryBean" id="catProxide"
property name="target" ref="cat"/property
property name="interceptorNames"
list
valueadvisor/value
/list
/property
/bean
4. bean class="cn.hncu.spring4x.aop.Cat" id="cat"/bean
!--//直接在切面bean中配置“切點(diǎn)的正則表達(dá)式”,省去“切點(diǎn)bean”的配置 用到這個(gè)類 org.springframework.aop.support.RegexpMethodPointcutAdvisor --
bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor"
property name="advice"
bean class="cn.hncu.spring4x.aop.AroundAdvice"/bean
/property
property name="patterns"
list
value.*run.*/value
/list
/property
/bean
!-- 自動(dòng)代理 --
bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/bean
5. bean class="cn.hncu.spring4x.aop.Cat" id="cat"/bean
!--//直接在切面bean中配置“切點(diǎn)的正則表達(dá)式”,省去“切點(diǎn)bean”的配置 用到這個(gè)類 org.springframework.aop.support.RegexpMethodPointcutAdvisor --
bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor"
property name="advice"
bean class="cn.hncu.spring4x.aop.AroundAdvice"/bean
/property
property name="patterns"
list
value.*run.*/value
/list
/property
/bean
!-- 自動(dòng)代理 --
bean class="cn.hncu.spring4x.aop.MyAutoProxy"/bean
面向切面編程(AOP),就是關(guān)注程序運(yùn)行的過(guò)程,切面就是要把方法切開(kāi),分別執(zhí)行前,執(zhí)行中,執(zhí)行后(可能更細(xì)化)等多個(gè)步驟,分別針對(duì)這三個(gè)階段進(jìn)行處理。以獲得邏輯過(guò)程中各部分之間低耦合性的隔離效果。
具體使用場(chǎng)景:
事務(wù)管理:我們?cè)诓僮鲾?shù)據(jù)庫(kù)的時(shí)候需要在操作前打開(kāi)事務(wù),結(jié)束后提交事務(wù)(或回滾事務(wù)),按往常的編碼方式,我們會(huì)在每個(gè)方法前、后都添加一些事務(wù)操作的重復(fù)的代碼,使得每個(gè)類都與事務(wù)操作相耦合;而使用了AOP,代碼上看上去就是直接操作的數(shù)據(jù)庫(kù),而我們通過(guò)某種機(jī)制,可讓代碼在你不察覺(jué)的情況下進(jìn)行了事務(wù)開(kāi)啟和提交(或回滾),事實(shí)上Spring就提供了這種事務(wù)機(jī)制。
差不多的場(chǎng)景還有日志的記錄
1.首先創(chuàng)建一個(gè)自定義注解攔截Controller類,代碼如下
/**
* 自定義注解 攔截Controller
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ControllerLog {
String desc() default "";//標(biāo)示默認(rèn)打印空
}
2.創(chuàng)建一個(gè)打印日志的切面類,引入切面注解@Aspect,
新建方法代碼如下:
// Controller層切點(diǎn)
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void recordLog() {
}
@Around("recordLog()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// ExPatternParser.initLogger();
long start = System.currentTimeMillis();
Object[] args = pjp.getArgs();
String remark = this.getControllerMethodDescription(pjp);
Object retVal = null;
try {
retVal = pjp.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
logger.error("請(qǐng)求失敗" + e.toString(),e);
remark = remark + "。Exception Cause By " + e.toString();
throw e;
}finally{
long end = System.currentTimeMillis();
long cost = end - start;
//打印訪問(wèn)日志
// Controller中所有方法的參數(shù),前兩個(gè)分別為:Request,Response
if(args != null args.length 0){
Object o = args[0];
if(o instanceof HttpServletRequest){
HttpServletRequest request = (HttpServletRequest) args[0];
PrintLog.visit(request, cost,remark);
}
}
}
return retVal;
}
/**
* 獲取注解中對(duì)方法的描述信息 用于Controller層注解
* @param joinPoint切點(diǎn)
* @return 方法描述
* @throws Exception
*/
public static String getControllerMethodDescription(ProceedingJoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
ControllerLog controllerLog = method.getAnnotation(ControllerLog.class);
if(controllerLog !=null){
description =
controllerLog.desc();
}
break;
}
}
}
return description;
}
3.然后在每個(gè)Controller類上加上注解:
@ControllerLog(desc = "要 打印的日志內(nèi)容")
aop的事務(wù)代理機(jī)制最重要的放心是確定切入點(diǎn),面,通知.具體看代碼,下面是在spring中配置的我自己寫的一個(gè)異常處理的aop作用類 ,該配置切入面在于在controller包下的所有類的所有注解為aspect的切面類,通知類型為表示在目標(biāo)方法之前切入,切入點(diǎn)為controller包下的所有類所有方法.至于樓主所說(shuō)的靜態(tài)方法對(duì)于事務(wù)機(jī)制應(yīng)該沒(méi)什么區(qū)別吧,只要用within方法一樣可以的
!-- 定義共同處理組件 --
bean id="loggerBean"
class="org.tedu.cloudnote.aspect.LoggerBean"
/bean
!-- 將loggerBean組件切入到Controller方法上 --
aop:config
!-- 要切入哪個(gè)共同處理組件,ref指定共同組件id值 --
aop:aspect ref="loggerBean"
!-- aop:before表示在目標(biāo)方法之前切入,
method指定方法名;pointcut指定目標(biāo)組件 --
aop:before method="logController"
pointcut="within(org.tedu.cloudnote.controller..*)"/
/aop:aspect
/aop:config
之后這個(gè)bean所定義的 自定義類的代碼如下 ,希望樓主給個(gè)采納,如果問(wèn)友喜歡,也可以給我個(gè)贊哦,摸摸大
package org.tedu.cloudnote.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//封裝共同處理的組件
@Component//掃描,等價(jià)于bean定義
@Aspect//等價(jià)于aop:aspect ref=""
public class LoggerBean {
//要在Controller.execute開(kāi)始位置切入
//方法規(guī)則:public void 方法名(){...} (前置通知)
@Before("within(org.tedu.cloudnote.controller..*)")
//等價(jià)于aop:before method="logController" pointcut=""
public void logController(){
System.out.println("進(jìn)入Controller組件處理");
}
}