zoukankan      html  css  js  c++  java
  • 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.写测试类

    二  示例

    配置文件实现

    1.创建项目SpringAop1

    2.导入需要的包

    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 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.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">
                       
                      <!-- 声明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.写测试类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.创建项目SpringAop2

    2.导入需要的包(同上)

    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层时,可以完全不作异常处理,而且创建一个专门的异常通知切面,由这个异常处理通知类专门负责处理各种异常。

  • 相关阅读:
    Java实现水仙花数
    CSS3属性选择器
    Word快捷键
    Java实现百钱买百鸡
    某专业人士给中国计算机专业学生的建议
    经典名言警句
    面试问题和思路
    情商
    Java注意的地方
    唯大英雄能真本色——Leo鉴书34
  • 原文地址:https://www.cnblogs.com/mlan/p/11060356.html
Copyright © 2011-2022 走看看