Spring-03

8 篇文章 0 订阅

1 aop编程的一些概念
2 使用 Spring 创建代理对象(注解方式)
3 关于切入点相关的参数的说明
4 环绕通知
 

一、AOP编程的一些概念

为什么要用AOP:可以看这篇文章(26条消息) 为什么需要使用Spring AOP(代理模式)_清思越的博客-CSDN博客

Aspect切面:横切性关注点的抽象

Joinpoint连接点:指的是拦截到的点,在spring中,指的就是被拦到的方法,比如addUser()等

pointCut 切入点:指的是对那些连接点进行拦截,比如,对所有的以get开头的方法进行计时

Advice 通知:拦到 Joinpoint 以后,要做的动作就叫通知,有前置通知、后置通知、最终通知、例外通知、环绕通知

Target 被代理的目标对象

Weave 织入:将Aspect 应用到目标对象的过程,经过织入以后,代理对象就产生了

二、使用 spring 创建代理对象(注解方式)

spring中进行AOP 编程,有两种方式:

        注解方式

        XML配置方式

1)注解方式:

  (1) 要导入相应的jar,加入配置构建路径
              aspectjweaver-1.8.9.jar 
              cglib-3.2.2.jar
         
                   如果用maven,则依赖如下
                         

  <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.8.9</version>
  </dependency>
  <dependency>
       <groupId>cglib</groupId>
       <artifactId>cglib</artifactId>
       <version>3.2.2</version>
   </dependency>

(2)创建spring的主配置文件,打开AOP的名称空间

<?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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<context:component-scan base-package="com.dao"/>
	<context:component-scan base-package="com.servlet"/>
	
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

(3)切面类

package com.aop;

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  //交给spring管理
public class Myaspect {
	/*excution表示要拦截的正在执行的方法
	  excution(int)里面的int表示要拦截的方法的返回值
	  excution(*)表示不管什么样的返回值都拦截
	*/
/*
 *  excution(“返回值 拦截的方法”)
    excution("*  com.dao.UserDao.*(int,String)")下面对应
    excution("返回值   拦截那个类下的那个方法.*(*表示所有方法)(int,String代表这个方法的返回值是什么,不在意返回值的话就(..))
 */

	@Pointcut("execution(* com.dao.UserDaoImpl.*(..))") //切入点,想要对那些方法进行拦截
	private void anyMethod() {}
	
	//我要拦的不是pointCut里面的这些方法吗,那么在拦截这些方法之前我要执行我下面这个事
	@Before("anyMethod()")
	public void  beforeMethod() {
		System.out.println("前置通知触发了");
	}
	
	//后置通知:和前置通知相对应
	@AfterReturning("anyMethod()")
	public void afterMethod() {
		System.out.println("后置通知触发了");
	}
	//最终通知
	@After("anyMethod()")
	public void finallyMethod() {
		System.out.println("最终通知触发了");
	}
	
	//例外通知
	@AfterThrowing("anyMethod()")
	public void execptionMethod() {
		System.out.println("出现异常,例外通知触发了");
	}
	
	
	
}


                    execution() //表示拦截正在执行的方法
                    * //表示不管方法的返回值是什么都拦
                    com.dao.UserDaoImpl //表示拦截哪个包下的哪个类
                    * 表示不管这个方法的名字是什么
                    (..) //表示不管方法的参数是什么 

 3 关于切入点相关的参数的说明

  //例 通过 JoinPoint 叁数,得到方法的名称和得到目标对象
         

   @Before("anyMethodAAA()") 
            public void beforMethod(JoinPoint point) {
                //得到被拦截的方法的名称
                String methodName=point.getSignature().getName();
                if("delUser".equals(methodName)) {
                    System.out.println("将调用删除方法,日志已记录...");
                }
                
                //得到目标对象 
                UserDaoImpl imp=(UserDaoImpl)point.getTarget();
                System.out.println("目标对象的userName属性值是:"+imp.getUserName());
                
                //得到方法的参数
                Object  [] params =point.getArgs(); 
                for(Object param:params) {
                    System.out.println(param);
                }
                
                    
                System.out.println("前置通知触发了");
            }
        
         //例子 进一步限定切入点的条件 ,只拦截带两个参数的                  
            @Before("anyMethodAAA()&&args(a,b)")  //前置通知
            public void beforMethod(String a,String b) {
                System.out.println("得到的参数是"+ a  +" 和 "+ b);
                System.out.println("前置通知触发了");
            }
            
            这个通知,将只能作用于带两个 String 参数的方法
            
            


         //例子 取得方法执行的返回值
         

   @AfterReturning(pointcut = "anyMethodAAA()",returning = "result")  //后置通知
            public void afterMethod(int result) {
                System.out.println("方法的返回值是 "+result);
                System.out.println("后置通知触发了");
            }
            
            经过上面的处理以后,只有接口中有int型返回值的方法才能触发上面的后置通知,比如下面这个方法
                            public int getUserCount() {
                                         System.out.println("getUserCount 执行了");
                                         return 9/3;
                                    }
                        

            
        
//例子 取得异常信息
             

@AfterThrowing(pointcut="anyMethodAAA()",throwing = "ex")
            public void exceptionMethod(Exception ex) {
                System.out.println("出错,异常信息是"+ex.getMessage());
                System.out.println("出现异常,例外通知触发了");
            }
  

4、环绕通知


		@Pointcut("execution(* com.dao.UserDaoImpl.*(..))")
		private void anyMethodAAA() {}
		
		@Around("anyMethodAAA()")
		public Object aroundMethod(ProceedingJoinPoint point) {
			Object result=null;
	
			String methodName=point.getSignature().getName();
			System.out.println("当前拦到的方法是:"+methodName);
			
			try {
				System.out.println("环绕通知 前置通知触发了");
				//让目标方法执行
				result=point.proceed();
				
				System.out.println("环绕通知 后置通知触发了");
				
			}catch(Throwable ex) {
				ex.printStackTrace();
				System.out.println("环绕通知 例通知触发了");
			}finally {
				System.out.println("环绕通知 最终知触发了");
			}
					
			return result;
			
		}

实际项目中,我们哪些地方需要做切面呢?

1)数据访问层

2)控制层

3)业务层

一般来说AOP主要用于日志记录、权限控制

             

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值