Spring之AOP
阿新 • • 發佈:2020-08-08
Spring之AOP
面向切面程式設計(方面),利用 AOP 可以對業務邏輯的各個部分進行隔離,從而使得業務邏 輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。 通俗描述:不通過修改原始碼方式,在主幹功能裡面新增新功能。
AOP底層原理
JDK動態代理
cglib動態代理
AOP(JDK 動態代理)
建立介面,定義方法
public interface UserDao {
public int add(int a, int b);
public String update(String id);
}
建立介面實現類,實現方法
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public String update(String id) {
return id;
}
}
使用Proxy類建立介面代理物件
public class JDKProxy {
public static void main(String[] args) {
Class[] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int add = dao.add(1, 2);
System.out.println("result=" + add);
}
}
class UserDaoProxy implements InvocationHandler{
//建立的是誰的物件,把誰傳遞過來
private Object obj;
public UserDaoProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法執行之前---" + method.getName() + "---傳遞的引數:" + Arrays.toString(args));
Object invoke = method.invoke(obj, args);
System.out.println("方法執行之後");
return invoke;
}
}
AOP術語
連線點
類裡面,哪些方法可以被增強,這些方法被稱為連線點。
切入點
實際被真正增強的方法,成為切入點。
通知(增強)
實際增強的邏輯部分稱為通知(增強)
通知有多種型別
前置通知
後置通知
環繞通知
異常通知
最終通知
切面
是動作,把通知應用到切入點的過程。
AOP操作
Spring框架一般都是基於AspectJ實現AOP操作。AspectJ不是Spring組成部分,獨立AOP框架,一般把AspectJ和Spirng框架一起使用,進行AOP操作。
AOP相關依賴
切入點表示式
切入點表示式作用:知道對哪個類裡面的哪個方法進行增強
語法結構: execution([許可權修飾符] [返回型別] [類全路徑] [方法名稱]([引數列表]) )
舉例 1
對cn.xupengzhuang.spring5.dao.UserDao類裡面的 add 進行增強
execution(* cn.xupengzhuang.spring5.dao.UserDao.add(..))
舉例 2
對cn.xupengzhuang.spring5.dao.UserDao類裡面的所有的方法進行增強
execution(* cn.xupengzhuang.spring5.dao.UserDao.* (..))
舉例 3
對 cn.xupengzhuang.spring5.dao.UserDao 包裡面所有類,類裡面所有方法進行增強
execution(* cn.xupengzhuang.spring5.dao.*.* (..))
AOP 操作(AspectJ 註解)
建立被增強類
@Component
public class UserDao {
public void add(){
System.out.println("dao add");
}
}
建立增強類
@Component
@Aspect //生成代理物件
public class UserDaoProxy {
//相同切入點抽取
@Pointcut(value = "execution(* cn.xupengzhuang.spring5.aop.dao.UserDao.add(..))")
public void pointdemo() {
}
//前置通知
@Before(value = "pointdemo")
public void before() {
System.out.println("before.........");
}
//後置通知(返回通知)
@AfterReturning(value = "pointdemo")
public void afterReturning() {
System.out.println("afterReturning.........");
}
//最終通知
@After(value = "pointdemo")
public void after() {
System.out.println("after.........");
}
//異常通知
@AfterThrowing(value = "pointdemo")
public void afterThrowing() {
System.out.println("afterThrowing.........");
}
//環繞通知
@Around(value = "pointdemo")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws
Throwable {
System.out.println("環繞之前.........");
//被增強的方法執行
proceedingJoinPoint.proceed();
System.out.println("環繞之後.........");
}
}
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:context="http://www.springframework.org/schema/context"
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/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 開啟註解掃描 -->
<context:component-scan base-package="cn.xupengzhuang.spring5.aop"></context:component-scan>
<!-- 開啟 Aspect 生成代理物件-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
純註解方式
@Configuration
@ComponentScan(basePackages = {"cn.xupengzhuang.spring5"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}