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层时,能够彻底不做异常处理,并且建立一个专门的异常通知切面,由这个异常处理通知类专门负责处理各类异常。

相关文章
相关标签/搜索