Spring Aop 面向切面編程
Aop 採用橫向抽取機制,底層採用JDK動態代理.
- JointPoint 連接點: 所謂連接點是指哪些被攔截到的點,在spring中,這些點指的就是方法,因爲spring只支持方法類型的連接點.
詳解:通知指業務接口中的方法均爲連接點…UserDaoImpl中的方法
- pointCut 切入點: 所謂切入點是指我們對哪些JoinPoint進行攔截的定義.
詳解:我們對哪些Joinpoint進行攔截的定義,addUser().
- Advice(通知/增強): 攔截到JointPoint之後所要做的事情就是通知,
通知有5種。爲分前置通知,後置通知,異常通知,最終通知,環繞通知。 詳解:攔截的目標對象的addUser()方法,時機(之前/之後等) 執行,通知切面完成功能.
- Target 目標對象 :代理的目標對象. UserDaoImpl.
- 切面aspect :泛指業務邏輯根據動態代理的例子. check(),printLog()可以理解爲切面.
列:aop練習
User.java
public class User {
private String id;
private String name;
public User() {
// TODO Auto-generated constructor stub
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
UserDao.java
/**
* 代理接口(目標對象實現的接口)
*
*/
public interface UserDao {
public void save();
public void update();
public void query();
public void delete(int id);
}
public class UserDaoImpl implements UserDao {
/*
* save()是切入點
*/
public void save() {
// TODO Auto-generated method stub
System.out.println("執行save..");
}
public void update() {
// TODO Auto-generated method stub
System.out.println("執行update..");
}
public void query() {
// TODO Auto-generated method stub
System.out.println("執行query.. 發成異常");
int rs=100/0;
}
public void delete(int id) {
// TODO Auto-generated method stub
System.out.println("執行delete");
}
}
MyAspect.java切面
public class MyAspect {
/**
* 切面
*/
public void check(){
System.out.println("切面---檢查權限 ---前置通知");
}
public void writeLog(){
System.out.println("寫入日誌---後置通知");
}
//ProceedingJoinPoint 連接點
public Object aroud(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("前");
System.out.println("連接點方法參數:"+joinPoint.getArgs());//連接點方法參數
//joinPoint.getArgs().length參數長度
for(int i=0;i<joinPoint.getArgs().length;i++){
System.out.println("連接點參數值:"+joinPoint.getArgs()[i]);
}
System.out.println(joinPoint.getTarget());//
Object ret=joinPoint.proceed();//執行連接點
System.out.println("ret=="+ret);
System.out.println("後");
return ret;
}
public void afterThrowing(Throwable ex){
System.out.println("異常通知"+ex);
}
public void after(){
System.out.println("最終通知֪");
}
}
bean.xml實現
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1實例化目標對象 -->
<!-- 配置目標對象 -->
<bean id="userDao" class="com.iotek.user.dao.UserDaoImpl"></bean>
<!-- 2實例化切面:將切面交給spring容器管理 -->
<bean id="myAspect" class="com.iotek.user.dao.MyAspect"></bean>
<!-- 3 寫約束: xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd -->
<!-- 4 書寫代理對象:通過aop的配置完成對目標類產生代理 -->
<aop:config>
<!--5 寫切入點pointCut expression:切面表達式 -->
<aop:pointcut expression="execution(* com.iotek.user.dao.UserDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* com.iotek.user.dao.UserDaoImpl.update(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* com.iotek.user.dao.UserDaoImpl.delete(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* com.iotek.user.dao.UserDaoImpl.query(..))" id="pointcut4"/>
<!--6 寫切面aspect pointcut-ref:引用切入點名稱 -->
<aop:aspect ref="myAspect">
<!-- 7通知advice:前置通知 -->
<aop:before method="check" pointcut-ref="pointcut1"/>
<!-- 8後置通知 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2"/>
<!-- 9環繞通知 -->
<aop:around method="aroud" pointcut-ref="pointcut3"/>
<!-- 10異常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
<!-- 11最終通知 (不管有無異常都會執行) -->
<aop:after method="after" pointcut-ref="pointcut4"/>
</aop:aspect>
</aop:config>
</beans>
測試
public class SpringTest {
/**
* 前置通知測試
*/
@Test
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao=(UserDao)context.getBean("userDao");
userDao.save();
userDao.update();
}
/**
* 後置通知測試
*/
@Test
public void test2(){
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao=(UserDao)context.getBean("userDao");
userDao.update();
}
/**
* 環繞通知測試
*/
@Test
public void test3(){
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao=(UserDao)context.getBean("userDao");
userDao.delete(100);
}
/**
* 異常通知
*/
@Test
public void test4(){
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao=(UserDao)context.getBean("userDao");
userDao.query();
}
}
結果: