## 步驟
1. 導入AOP約束(命名空間).
2. 配置目標對象.
3. 配置通知對象.
4. 配置將通知織入目標對象.
## 步驟
```
~~~
<!-- spring 中基于XML的AOP配置步驟
1.把通知Bean也交給spring來管理.
2.使用aop:config標簽表名開始AOP的配置.
3.使用aop:aspect標簽表名開始AOP的配置.
id屬性:是給切面提供一個唯一標識.
ref屬性:是指定通知類bean的ID.
4.在aop:aspect標簽的內部使用對應標簽來配置通知的類型.
我們現在示例是讓通知類的方法在切入點方法執行之前執行,所以是前置通知.
aop:before :表示配置前置通知.
method屬性:用于指定通知類中哪個方法是前置通知.
pointcut屬性:用于指定切入點表達式,該表達式的含義指的是對業務層中哪些方法增強
-->
~~~
```
## 代碼
目標類:
~~~
public class UserServiceImpl implements UserService
{
@Override
public void save()
{
System.out.println("save");
}
@Override
public void delete()
{
System.out.println("delete");
}
@Override
public void update()
{
System.out.println("update");
}
@Override
public void get()
{
System.out.println("get");
}
@Override
public String toString()
{
return "UserServiceImpl{}";
}
}
~~~
通知類:
~~~
public class MyAdvice
{
//前置通知:目標方法運行之前調用
public void before()
{
System.out.println("前置通知");
}
//后置通知:如果出現異常不會調用
public void afterRunning()
{
System.out.println("后置通知,異常不調用");
}
//環繞通知:在目標方法之前和之后都調用
public Object around(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("環繞通知之前");
//調用目標方法
Object proceed = pjp.proceed();
System.out.println("環繞通知之后");
return proceed;
}
//異常攔截通知:如果出現異常就會調用
public void afterException()
{
System.out.println("異常通知");
}
//后置通知:無論是否出現異常都會調用
public void after()
{
System.out.println("后置通知,異常調用");
}
}
~~~
配置文件:
~~~
<?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: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/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">
<!--配置目標對象-->
<bean name="userServiceTarget" class="com.like.serviceImpl.UserServiceImpl"/>
<!--配置通知對象-->
<bean name="myAdvice" class="com.like.aspect.MyAdvice"/>
<aop:config>
<!--配置切入點
public void com.like.serviceImpl.UserServiceImpl.save() //完整寫法
void com.like.serviceImpl.UserServiceImpl.save() //省略public
* com.like.serviceImpl.UserServiceImpl.save() //不對返回值做要求
* com.like.serviceImpl.UserServiceImpl.*() //所有方法,必須是空參
* com.like.serviceImpl.UserServiceImpl.*(..) //所有方法,任意參數,可以沒參數
* ..UserServiceImpl.*(..) //當前包及其子包
* com.like.serviceImpl.*ServiceImpl.*(..) //所有方法,ServiceImpl后綴的類
* com.like.serviceImpl.*ServiceImpl.*(int) //指定int類型
* com.like.serviceImpl.*ServiceImpl.*(*) //任意類型,但是必須有參數
* com.like.serviceImpl..*ServiceImpl.*(..) //所有方法,ServiceImpl后綴的類還有它的子包
-->
<aop:pointcut id="pc" expression="execution( * com.like.serviceImpl.*ServiceImpl.*(..))"/>
<!--配置切面, id是切面的唯一標識.ref是通知類的引用-->
<aop:aspect id="myAdvicexxxx" ref="myAdvice">
<!--指定名為before方法作為前置通知-->
<aop:before method="before" pointcut-ref="pc"/> //這里是共用一個切入點了,如果使用ponitcut屬性可以單獨制定切入點
<!--指定名為afterRunning方法作為后置通知-->
<aop:after-returning method="afterRunning" pointcut-ref="pc"/>
<!--指定名為around方法作為環繞通知-->
<aop:around method="around" pointcut-ref="pc"/>
<!--指定名為afterException方法作為異常通知-->
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<!--指定名為after方法作為最終通知(有異常也通知)-->
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
~~~
調用:
~~~
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userServiceTarget"); //如果符合要求,獲取到的就是代理對象.是無法獲取被代理對象的
System.out.println(userService);
~~~
## 通用化切入點表達式
所有切面都能使用. 但是必須在所有切面之前.
~~~
<aop:config>
<aop:pointcut id="advice" expression="execution(* com.like.service.impl.*ServiceImpl.*(..))"/>
<aop:aspect ref="logger">
<aop:around method="around" pointcut-ref="advice"/>
</aop:aspect>
</aop:config>
~~~
## 單個切面使用
~~~
<aop:config>
<aop:aspect ref="logger">
<aop:pointcut id="ad1" expression="execution(* com.like.service.impl.*ServiceImpl.*(..))"/>
<aop:around method="around" pointcut-ref="ad1"/>
</aop:aspect>
</aop:config>
~~~
## 單個方法切入點表達式
~~~
<aop:config>
<aop:aspect ref="logger">
<aop:around method="around" pointcut="execution(* com.like.service.impl.*ServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
~~~
## 注解方式
~~~
<?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: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/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">
<!--配置目標對象-->
<bean id="userServiceTarget" class="com.like.serviceImpl.UserServiceImpl"/>
<!--配置將通知織入目標對象-->
<bean id="myAdvice" class="com.like.aspect.MyAdvice"/>
<!--開啟使用注解完成織入-->
<aop:aspectj-autoproxy/>
</beans>
~~~
~~~
package com.like.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
//用該注解表示是通知類
@Aspect
public class MyAdvice
{
@Pointcut("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void pc(){}
//指定該方法是前置通知,并指定切入點
@Before("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void before()
{
System.out.println("前置通知");
}
//后置通知:如果出現異常不會調用
@AfterReturning("MyAdvice.pc()") //這是簡寫方法,這樣講就不用為每個通知都指定范圍了
public void afterRunning()
{
System.out.println("后置通知,異常不調用");
}
//環繞通知:在目標方法之前和之后都調用
@Around("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("環繞通知之前");
//調用目標方法
Object proceed = pjp.proceed();
System.out.println("環繞通知之后");
return proceed;
}
//異常攔截通知:如果出現異常就會調用
@AfterThrowing("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void afterException()
{
System.out.println("異常通知");
}
//最終通知:無論是否出現異常都會調用
@After("execution( * com.like.serviceImpl.*ServiceImpl.*(..))")
public void after()
{
System.out.println("后置通知,異常調用");
}
}
~~~
## 注意
后置通知和一場通知最終只能執行一個.
- Maven
- 概述
- 常用命令
- 生命周期
- scope詳解
- maven概念模型圖
- IDEA創建maven工程
- 創建maven web項目
- 沖突解決
- pom文件標簽詳解
- maven工程拆分與聚合的思想
- 父子工程的創建
- 工程和模塊的關系以及集成和依賴的概念
- 父子工程添加依賴
- 父子工程的三種啟動方式
- Struts2
- 執行流程
- 配置
- action的使用
- 獲取Servlet的API
- result標簽的視圖配置
- struts2屬性封裝
- struts2模型封裝
- OGNL
- 值棧(ValueStack)
- 值棧context區存數據
- 值棧root區
- struts2對el的增強
- #,%,$符號使用
- 值棧擴展
- 攔截器
- 自定義攔截器
- 方法攔截器
- 注解方式
- Hibernate
- 配置
- 簡單crud
- 持久化類編寫規范
- OID
- 持久化類三種狀態
- 一級緩存
- 查詢
- session與當前線程綁定
- hibernate一對多配置
- 冗余SQL語句的原因
- hibernate多對多配置
- 級聯操作
- 對象導航查詢
- JPA
- JPA單表CRUD
- JPA多種查詢
- JPA一對多關系映射
- JPA一對多操作
- JPA多對多關系映射
- JPA多對多操作
- QBC查詢
- 離線條件查詢(DetachedCriteria)
- SpringMVC
- 環境搭建
- 常用注解
- 請求參數綁定
- 綁定基本類型和字符串
- 綁定實體類型
- 解決中文亂碼
- 綁定集合類型
- 自定義類型轉換器
- 獲取Servlet的API
- 響應字符串
- 響應void
- 響應ModelAndView
- 響應forward和redirect
- 響應過濾靜態資源
- 響應json
- 文件上傳基礎
- SpringMVC上傳文件
- 跨服務器文件上傳
- 攔截器
- SpringMVC異常
- ControllerAdvice
- SpringMVC默認處理方式
- 概述
- @ExceptionHandler
- 消息轉換器
- SpringMVC跨域
- Spring
- 概述
- IoC快速入門
- ApplicationContext三個常用實現類
- beanFactory和ApplicationContext區別
- bean創建三種方式
- POJO和Javabean的區別
- bean作用范圍
- bean對象生命周期
- spring的依賴注入
- DI的屬性注入方式
- 常用注解
- Spring新注解
- Spring整合連接池
- Spring的IOC注解配置
- Spring完全使用注解
- Spring整合junit
- AOP
- AOP配置
- JDBCTemplate
- JDBCTemplate在IOC中使用
- JDBCTemplate的CRUD
- JDBCTemplate在dao中使用
- 聲明式事務
- spring事務API
- 事務XML配置
- 事務注解配置
- 全注解事務
- Spring編程式事務
- 整合SSH(XML版本)
- 整合SSH(半XML半注解)
- Spring5新特性
- MyBatis
- 概述
- 用maven創建MyBatis
- 將數據庫配置單獨文件
- typeAliases標簽
- MyBatis的CRUD
- MyBatis實現Dao層開發
- 使用dao和代理類的區別
- MyBatis連接池
- MyBatis事務
- MyBatis動態SQL
- 多表操作
- 多表一對一
- 多表一對多
- 多表多對多
- JNDI
- 延遲加載和立即加載
- 延遲加載
- 一級緩存
- 二級緩存
- MyBatis注解
- MyBatis注解CRUD
- 注解實體類屬性和字段對應關系
- MyBatis注解一對一和一對多
- MyBatis注解二級緩存
- SSM整合
- 搭建環境
- SpringBoot
- SpringBoot核心功能
- 快速入門
- SpringBoot配置文件
- yml配置文件語法
- 配置文件與配置類的屬性映射方式
- 端口和映射路徑
- 日志級別
- 訪問靜態資源
- SpringBoot注入方式一
- SpringBoot注入方式二
- 攔截器
- HikariCP連接池
- SpringBoot集成MyBatis
- 通用mapper
- SpringBoot事務
- SpringBoot集成Junit
- SpringBoot集成DataJPA
- SpringBoot集成Redis
- 使用SpringBoot提供的測試啟動類
- 使用MockMvc
- SpringCloud
- RestTemplate
- Eureka概述
- Eureka快速入門
- Eureka集群
- Eureka客戶端
- Eureka失效剔除和自我保護
- 負載均衡Ribbon
- Hystrix
- Hystrix服務降級
- Hystrix服務熔斷
- Feign
- Feign的熔斷機制
- Feign的請求壓縮和日志級別
- Zuul網關
- Zuul快速入門
- Zuul路由規則
- Zuul過濾器
- Zuul自定義過濾器
- Zuul負載均衡和熔斷
- Zuul高可用
- Zuul網關緩存
- SpringSecurity
- 快速入門
- SpringSecurity使用數據庫認證