spring AOP面向切面編程

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();
   	}
}

結果:

test3結果
標題test4結果

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章