1、AOP思考導入(指向プログラミング):縦コードの重複、横抽出溶液と呼ば:横
2、春AOPに:私たち自身の動的プロキシコードを記述する必要はありません、春には、管理対象オブジェクトは、我々は彼にいくつかのセットを作ることを提供し、動的プロキシオブジェクトを生成するコンテナできます。
図3に示すように、春AOPは、動的プロキシに基づいている - JDKProxy動的剤が好ましいです。
A)プロキシ動的プロキシ:プロキシオブジェクトがインタフェースを実装しなければなりません。
B)CGLIBダイナミック剤:最終プロキシオブジェクト継承に基づいて、変更することができません。
パッケージcom.Gary.serviceを。 パブリック インターフェースUserServiceの{ // 追加 のボイド保存(); // 削除 無効(削除)。 // 改 無効更新(); // チェック 無効)(検索します。 }
パッケージcom.Gary.serviceを。 パブリック クラス UserServiceImpl 実装UserServiceの{ @オーバーライド 公共 のボイドの保存(){ System.out.println("save()"); } @Override public void delete() { System.out.println("delete()"); } @Override public void update() { System.out.println("update()"); } @Override public void find() { System.out.println("find()"); } }
package com.Gary.test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.Gary.service.UserService; import com.Gary.service.UserServiceImpl; //UserService代理类 public class UserServiceProxy { //代理对象 UserServiceProxy //被代理对象 UserService public UserService getUserServiceProxy(UserService us) { return (UserService) Proxy.newProxyInstance(UserServiceProxy.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //增强代码 System.out.println("开启事务"); //需要调用原始的方法 Object invoke = method.invoke(us, args); System.out.println("提交/回滚"); return invoke; } }); } }
package com.Gary.test; import org.junit.Test; import com.Gary.service.UserService; import com.Gary.service.UserServiceImpl; public class AopTest { @Test public void Test1() { UserServiceProxy usProxy = new UserServiceProxy(); UserService us = new UserServiceImpl(); UserService us_PowerUp = usProxy.getUserServiceProxy(us); us_PowerUp.find(); } }
4、Spring aop相关名词说明
代理写小学生暑假作业,3年级以下
目标对象:UserService(小学生作业)
被代理对象:被UserServiceProxy增强后的UserService(用你的知识去写的作业)
JoinPoint、连接点、目标对象中,哪些方法会被拦截;save,delete,update,find (所有要写的作业:数学、语文、英语、王者荣耀代上王者)
Pointcut切入点:筛选连接点,你最终要增强的方法;save,update,delete (小学生只让你给写数学语文英语,王者荣耀他自己上王者)
Advice通知/增强:要执行的增强代码 (你用你N年积攒的知识去完成小学暑假作业)
Introduction介入/引入:在执行时期动态加入一些方法或行为
Aspect切面:通知 + 切入点,通知应用到哪个切点
target目标:被代理对象 (小学生的作业)
weaving织入:把切面的代码应用到目标对象来创建新的代理对象的过程 (将你的脑子应用到写小学生的暑假作业上)
proxy代理:把切面的代码应用到目标对象来创建新的代理对象(利用你的知识去完成作业)
5、Spring aop配置:
a)导包:
i.基本包;
ii.spring-aspects和spring-aop ;
iii.aop联盟包 – aopalliance;
iv.aop织入包 - aspectj.weaver;
b)自定义通知,五种自定义通知类型:
i.before 前置通知
ii.after 最终通知(后置通知)
iii.afterReturning 成功通知(后置通知)
iv.afterThrowing 异常通知(后置通知)
v.around 环绕通知
在aop层创建一个MyAdvice.java自定义通知类
package com.Gary.aop; import org.aspectj.lang.ProceedingJoinPoint; //自定义通知类 public class MyAdvice { //before 前置通知 在目标方法前调用 public void before() { System.out.println("before()"); } //after 最终通知(后置通知)在目标方法后调用,无论是否出现异常都会执行 finally public void after() { System.out.println("after()"); } //afterReturning 成功通知(后置通知) 在目标方法执行后,并执行成功,如果方法出现异常,则不会调用 public void afterReturning(){ System.out.println("afterReturning()"); } //afterThrowing 异常通知(后置通知) 在目标方法执行出现异常的时候才会调用 public void afterThrowing() { System.out.println("after()"); } //around 环绕通知 需要我们手动调用目标方法,并且可以设置通知 public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("around before"); Object proceed = pjp.proceed(); System.out.println("around after"); return proceed; } }
c)配置applicationContext.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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 目标对象 --> <bean name="userService" class="com.Gary.service.UserServiceImpl"></bean> <!-- 通知对象 --> <bean name="myAdvice" class="com.Gary.aop.MyAdvice"></bean> <aop:config> <!-- 切入点 expression 切入点表达式 可以配置要增强的方法 public void com.Gary.service.UserServiceImpl.save() * com.Gary.service.*ServiceImpl.*(..) id 就是唯一标识 --> <aop:pointcut expression="execution(* com.Gary.service.*ServiceImplabc.*(..))" id="servicePc"/> <!-- 切面 通知+切入点 --> <aop:aspect ref="myAdvice"> <!-- 通知类型 --> <aop:before method="before" pointcut-ref="servicePc"/> <!-- 最终通知 后置通知 --> <aop:after method="after" pointcut-ref="servicePc"/> <!-- 成功通知 后置通知 --> <aop:after-returning method="afterReturning" pointcut-ref="servicePc"/> <!-- 异常通知 后置通知 --> <aop:after-throwing method="afterThrowing" pointcut-ref="servicePc"/> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="servicePc"/> </aop:aspect> </aop:config> </beans>