Spring框架:AOP程式設計
阿新 • • 發佈:2018-12-17
實現方法:動態代理設計模式
- JDK 的動態代理:針對實現了介面的類產生代理。InvocationHandler介面
- CGlib 的動態代理:針對沒有實現介面的類產生代理,應用的是底層的位元組碼增強的技術 生成當前類的子類物件,MethodInterceptor介面
JDK動態代理
-
建立介面和實現類
-
建立代理類,實現InvocationHandler介面
//建立被代理物件 private UserDao dao; public Agency(UserDao dao){ this.dao=dao; } //建立代理物件 public
-
測試
//獲取代理物件
*//* UserDao u = new U();*//*
//建立代理類物件
Agency agency = new Agency(u);
//建立代理物件
UserDao um = agency.CreatAgency();
//呼叫方法
um.sing();
CGlib動態代理
實現介面MethodInterceptor,來自import org.springframework.cglib.proxy.MethodInterceptor;不要錯誤了
-
建立普通類:方法
-
建立代理器,實現MethodInterceptor介面
程式碼與上一個相同,區別的地方時建立代理物件的方法
//建立代理物件的方法 public UsersDaoImpl createdaili(){ Enhancer en=new Enhancer();//建立核心類 en.setSuperclass(user.getClass());//為其設定父類 en.setCallback(this);//設定回撥 return (UsersDaoImpl)en.create(); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 執行方法之前語句塊 Object o1 = methodProxy.invokeSuper(o, objects); 執行方法之後語句塊 return o1; }
-
測試:與JDK動態代理測試方法一致
AOP實現:以上兩種方式程式碼自動判斷實現
- 新增jar包
- 建立Aop增強類(本質普通類)
- 前置通知
- 返回通知
- 後置異常通知
- 後置最終通知
- 環繞通知:有返回值,必須返回,否則報錯
public Object around(ProceedingJoinPoint point) throws Throwable{}
- xml檔案新增名稱空間aop
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
-
設定配置檔案
<!--建立目標類物件--> <bean name="userService" class="com.itqf.spring.service.UserServiceImpl" /> <!--配置增強類物件--> <bean name="myAdvice" class="com.itqf.spring.aop.MyAdivce" /> <!-- 配置將增強織入目標物件--> <aop:config> <aop:pointcut id="pc" expression="execution(* com.itqf.spring.service.*ServiceImpl.*(..))"/> <aop:aspect ref="myAdvice"> <aop:before method="before" pointcut-ref="pc" /> <aop:after-returning method="afterReturning" pointcut-ref="pc" /> <aop:around method="around" pointcut-ref="pc" /> <aop:after-throwing method="afterException" pointcut-ref="pc" /> <aop:after method="after" pointcut-ref="pc" /> </aop:aspect> </aop:config> 注意:(1)環繞增強需要使用ProceedingJoinPoint 作為引數(2)注意標籤順序
-
切入點匹配規則:
public * addUser(com.pb.entity.User):“*”表示匹配所有型別的返回值。 示例:public int addUser(User u); public String addUser(User u); public void *(com.pb.entity.User):“*”表示匹配所有方法名。 示例:public void selectUser(User u); public void a(User u); public void addUser (..):“..”表示匹配所有引數個數和型別。 示例: public void addUser(int a) public void addUser(int b,int c) * com.pb.service.*.*(..):匹配com.pb.service 包下所有類的所有方法。 示例: public void com.pb.service.A.a(); public String com.pb.service.B.a(); * com.pb.service..*(..):匹配com.pb.service 包及子包下所有類的所有方法
獲取切入點資訊
通過aop類,新增引數JoinPoint物件獲取資訊
"切入點物件:"+jp.getTarget().getClass().getSimpleName(); "切入點方法:"+jp.getSignature(); "切入點的引數:"+jp.getArgs()[0];
特殊增強——Advisor前置增強實現步驟
- 建立增強類,實現MethodBeforeAdvice介面
- 在配置檔案,aop配置切入點後,加入
<aop:advisor advice-ref="增強類物件的id" pointcut-ref="切入點物件的id"/>
註解實現Aop
-
啟動aspectj註解
<aop:aspectj-autoproxy/>
-
在切面類上新增@Aspect
-
定義切面方法(任意),新增切入點註解@Pointcut(“execution(切入路徑)”)
-
@Before 前置 @After 最終 @Around 環繞 @AfterReturning 後置 @AfterThrowing 異常
eg: @Before("切入方法()")