Spring配置過程 (二)面向切面編程AOP

一  配置過程

1.建立項目

2.導包
    Spring的包
    增長:
    aopalliance
    aspectjweaver

3.建立Dao層接口及實現層

4.建立通知類及要執行的通知方法

5.配置ApplicationContext.xml

        配置bean
        配置AOP   aop:config
        配置切點   aop:pointcut
                         id
                         expression  "execution(針對的方法)"

        配置切面  aop:aspect
                         id
                         ref
        配置鏈接點
                         aop:before
                         aop:after
                         aop:after-returning    
                         aop:around    
                         aop:after-throwing

6.寫測試類
html

二  示例

配置文件實現

1.建立項目SpringAop1java

2.導入須要的包spring

3.建立Dao層接口IUserDaoexpress

package com.hp.dao;

public interface IUserDao {
	int login(String name,String password);
	int div(int a,int b);
}

建立Dao層實現UserDaoImplide

package com.hp.dao.impl;

import com.hp.dao.IUserDao;

public class UserDaoImpl implements IUserDao {

	@Override
	public int login(String name, String password) {
		if("admin".equals(name) && "123".equals(password)){
			System.out.println("登陸成功");
			return 1;
		}
		else{
			System.out.println("登陸失敗");
		}
		return 0;
	}

	@Override
	public int div(int a, int b) {
		
		int res=a/b;  //b=0時拋出異常
		return res;
		
	}

}

4.建立通知類及要執行的通知方法LogAdvice測試

package com.hp.advice;

import org.aspectj.lang.JoinPoint;

public class LogAdvice {
	
	public void before(JoinPoint jp){
		/*
		 * 如何才能知道調用的是哪個方法
		 * 給before方法添加一個參數JoinPoint
		 */
		
		String methodName = jp.getSignature().getName();     //獲取方法名
		Object[] args = jp.getArgs();     //獲取參數
		System.out.println("前置通知");
		System.out.println("將要執行:"+methodName+"方法");
		System.out.println("參數列表:");
		for (Object object : args) {
			System.out.println(object);
		}
	}
	
	public void after(JoinPoint jp){
		String methodName = jp.getSignature().getName();  
		System.out.println(methodName + "方法執行結束");
		System.out.println("後置通知");
	}
	
	public void afterReturning(Object res) throws Throwable{
		System.out.println("返回值:"+res);
		System.out.println("返回通知");
	}
	
	public void afterThrowing(Exception ex){
		System.out.println("異常信息:"+ex.getMessage());
		System.out.println("分母不能爲0");
	}
}

5.配置ApplicationContext.xmlspa

<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       			   http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/tx  
                            http://www.springframework.org/schema/tx/spring-tx.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-4.1.xsd">
                   
                  <!-- 聲明bean -->       
                  <bean id="IUserDao"  class="com.hp.dao.impl.UserDaoImpl" ></bean>
                  <bean id="logAdvice" class="com.hp.advice.LogAdvice"></bean>
        			
        		  <!-- 配置AOP -->
        		  <aop:config>
        		  <!-- 配置切入點 -->
        		  <!-- 第一個*表示訪問符和返回類型任意,括號裏的兩個點表示任意參數 -->
        		  	<aop:pointcut expression="execution(* com.hp.dao.*.*(..))"  id="logPoint" />
        		  	<!-- 配置切面 -->
        		  	<aop:aspect id="logAspect" ref="logAdvice" >
        		  		<!-- 配置鏈接點 -->
        		  		<aop:before method="before"  pointcut-ref="logPoint" /> 
        		  		<aop:after method="after" pointcut-ref="logPoint"/>
        		  		<aop:after-returning method="afterReturning" pointcut-ref="logPoint" returning="res"/>
        		  		<aop:after-throwing method="afterThrowing" pointcut-ref="logPoint"  throwing="ex"/>
        		  	</aop:aspect>
        		  </aop:config> 
</beans>

6.寫測試類MainTest3d

package com.hp.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.hp.dao.IUserDao;

public class MainTest {
	@Test
	public void login() throws Exception{
	ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");
	IUserDao iUserDao = (IUserDao) context.getBean("IUserDao");
	 iUserDao.login("admin", "123");
	 System.out.println("-------------");
	 iUserDao.div(1, 0);
	}
}
7.運行結果:

前置通知
將要執行:login方法
參數列表:
admin
123
登陸成功
login方法執行結束
後置通知
返回值:1
返回通知
-------------
前置通知
將要執行:div方法
參數列表:
1
0
div方法執行結束
後置通知
異常信息:/ by zero
分母不能爲0
8.項目結構:



註解實現

1.建立項目SpringAop2code

2.導入須要的包(同上)component

3.建立Dao層接口IUserDao

package com.hp.dao; public interface IUserDao { int login(String name,String password); int div(int a,int b); } 

建立Dao層實現UserDaoImpl

package com.hp.dao.impl;

import org.springframework.stereotype.Repository;

import com.hp.dao.IUserDao;
@Repository("IUserDao")
public class UserDaoImpl implements IUserDao {

	@Override
	public int login(String name, String password) {
		if("admin".equals(name) && "123".equals(password)){
			System.out.println("登陸成功");
			return 1;
		}
		else{
			System.out.println("登陸失敗");
		}
		return 0;
	}

	@Override
	public int div(int a, int b) {
		
		int res=a/b;  //b=0時拋出異常
		return res;
		
	}
}

4.建立通知類及要執行的通知方法LogAdvice

package com.hp.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component  //(把普通pojo實例化到spring容器中,至關於配置文件中的<bean id="" class=""/>)
public class LogAdvice {
	
	@Pointcut("execution(* com.hp.dao.*.*(..))")
	private void anyMethod(){}   //聲明一個切入點,anyMethod爲切入點名稱
	
	@Before("anyMethod()")
	public void before(JoinPoint jp){
		/*
		 *  如何才能知道調用的是哪個方法
		 *  給before方法添加一個參數JoinPoint
		 */
		
		String methodName = jp.getSignature().getName();//獲取方法名
		Object[] args = jp.getArgs();//獲取參數
		System.out.println("前置通知");
		System.out.println("將要執行:"+methodName+"方法");
		for (Object object : args) {
			System.out.println(object);
		}
	}

	@After("anyMethod()")
	public void after(JoinPoint jp){
		String methodName = jp.getSignature().getName();
		System.out.println(methodName+"方法執行結束");
		System.out.println("後置通知");
	}	
	
	@AfterReturning(pointcut ="anyMethod()", returning="res")
	public void afterReturning(Object res) throws Throwable{
		System.out.println("方法返回值:"+res);
		System.out.println("返回通知");
	}
	
	@AfterThrowing(pointcut = "anyMethod()", throwing="ex")
	public void afterThrowing(Exception ex){
		System.out.println("異常信息:"+ex.getMessage());
		System.out.println("分母不能爲0");
	}
}

5.配置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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.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-4.1.xsd">   <!-- spring註解 -->        <context:component-scan base-package="com.hp.dao,com.hp.advice" />                                      <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>

6.寫測試類MainTest

package com.hp.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.hp.dao.IUserDao; public class MainTest { @Test public void login() throws Exception{ ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml"); IUserDao iUserDao = (IUserDao) context.getBean("IUserDao"); iUserDao.login("admin", "123"); System.out.println("-------------"); iUserDao.div(1, 0); } } 
7.運行結果:
前置通知 將要執行:login方法 參數列表: admin 123 登陸成功 login方法執行結束 後置通知 返回值:1 返回通知 ------------- 前置通知 將要執行:div方法 參數列表: 1 0 div方法執行結束 後置通知 異常信息:/ by zero 分母不能爲0
8.項目結構:



三   問題研究

1. 在返回通知中,如何獲取返回值?
    xml中<aop:after-returning method="afterReturning" pointcut-ref="logPoint" returning="res"/>
    Advice中傳遞一個Object類型的res參數
2. 在異常通知中,如何獲取出現的異常?
    xml:<aop:after-throwing method="afterThrowing" pointcut-ref="logPoint"  throwing="ex"/>
    Advice中傳遞一個Exception類型的ex參數
    Advice中ex.getMessage()
3. 當異常出現時,返回通知和後置通知還會執行嗎?
     返回通知不會執行,後置通知會執行

4. 當後置通知與返回通知同時存在時,哪個先執行呢?
     執行順序按照在xml配置文件中的配置順序執行

四  XML配置方式與註解方式對比

1. 使用註解時,須要在XML配置文件中添加<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2. @ Component註解,至關於配置文件中的,<bean >
3. @ Pointcut註解,至關於配置文件中的,<aop:pointcut>
4. @ Aspect註解,至關於配置文件中的, <aop:aspect>
5. @ Before註解,至關於配置文件中的.<aop:before> after afterrunning afterthrowing around

注:異常通知,比較經常使用, 咱們在編寫Dao層和Service層時,能夠徹底不做異常處理,並且建立一個專門的異常通知切面,由這個異常處理通知類專門負責處理各類異常。

相關文章
相關標籤/搜索