spring aop

AOP中关键性概念
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.

目标(Target):被通知(被代理)的对象
注1:完成具体的业务逻辑

通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)
注2:完成切面编程

代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),
例子:外科医生+护士
注3:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的

切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。
(也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)

适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)

如何实现AOP
目标对象只负责业务逻辑代码
通知对象负责AOP代码,这二个对象都没有AOP的功能,只有代理对象才有

  1. AOP
    即面向切面编程

  2. AOP带来的好处
    让我们可以 “专心做事”
    案例:
    public void doSameBusiness (long lParam,String sParam){
    // 记录日志
    log.info(“调用 doSameBusiness方法,参数是:”+lParam);
    // 输入合法性验证
    if (lParam<=0){
    throws new IllegalArgumentException(“xx应该大于0”);
    }
    if (sParam==null || sParam.trim().equals("")){
    throws new IllegalArgumentException(“xx不能为空”);
    }
    // 异常处理
    try{ …
    }catch(…){
    }catch(…){
    }
    // 事务控制
    tx.commit();
    }

3 工具类org.springframework.aop.framework.ProxyFactoryBean用来创建一个代理对象,在一般情况下它需要注入以下三个属性:
proxyInterfaces:代理应该实现的接口列表(List)
interceptorNames:需要应用到目标对象上的通知Bean的名字。(List)
target:目标对象 (Object)

  1. 前置通知(org.springframework.aop.MethodBeforeAdvice):在连接点之前执行的通知()
    案例:在购书系统当中使用AOP方式实现日志系统

  2. 后置通知(org.springframework.aop.AfterReturningAdvice):在连接点正常完成后执行的通知
    案例:在线购书系统中,要求不修改BookBizImpl代码的情况下增加如下功能:对买书的用户进行返利:每买本书返利3元。(后置通知)
    即:每调用一次buy方法打印:“[销售返利][时间]返利3元。”

  3. 环绕通知(org.aopalliance.intercept.MethodInterceptor):包围一个连接点的通知,最大特点是可以修改返回值,由于它在方法前后都加入了自己的逻辑代码,因此功能异常强大。
    它通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用,这样目标方法就不会执行)
    案例:修改日志系统不光要输出参数,还要输出返回值(环绕通知)

这个接口里面没有定义方法,我们要求我们的类必须实现afterThrows这个方法

public void afterThrowing( [Method method,] [Object args,] [Object target,] Throwable throwable );

前面三个参数都是可选的,只有第三个参数是必须的,同时我们还可以在同一个类中定义这个方法的多个版本,如:

public void afterThrowing( MyException1 ex ) {}

public void afterThrowing( MyException2 ex ) {}

具体那个方法被调用则根据具体的Exception来判断,由AOP容器自动识别 执行

  1. 异常通知(org.springframework.aop.ThrowsAdvice):这个通知会在方法抛出异常退出时执行
    案例: 书本价格为负数时抛出一个异常,通过异常通知取消此订单

  2. 适配器(org.springframework.aop.support.RegexpMethodPointcutAdvisor) 适配器=通知(Advice)+切入点(Pointcut)
    案例:通过适配器解决发书评时也返利的问题
    .*buy

  3. 请使用接口接收返回的代理对象
    A

B C

A a1 = new B();
A a2 = new C();
B b = (B) a2;

核心点
通知
前置通知
实现org.springframework.aop.MethodBeforeAdvice接口
买书、评论前加系统日志

@Override
	public void before(Method method, Object[] arg1, Object target) throws Throwable {
		// TODO Auto-generated method stub
    
		//获取类名
		String targetName=target.getClass().getName();
		//获取方法名 
		String methodName=method.getName();
		//携带参数
		String params=Arrays.toString(arg1); 
		String msg="【系统日志】:正在调用->"+targetName+"."+methodName+",携带参数:"+params;
		System.out.println(msg);
	}
	后置通知
	实现org.springframework.aop.AfterReturningAdvice接口
	买书返利(存在bug)
@Override
	public void afterReturning(Object returnValue, Method method, Object[] arg2, Object target) throws Throwable {
		// TODO Auto-generated method stub
		//获取类名
				String targetName=target.getClass().getName();
				//获取方法名 
				String methodName=method.getName();
				//携带参数
				String params=Arrays.toString(arg2); 
				String msg="【后置通知,红包返利】:正在调用->"+targetName+"."+methodName+",携带参数:"+params+",返回值"+returnValue;
				System.out.println(msg);
	}
	环绕通知
	org.aopalliance.intercept.MethodInterceptor
	类似过滤器,会包括切入点,目标类前后都会执行代码。
@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		// TODO Auto-generated method stub
		//获取到目标类
		Object target = arg0.getThis();
		//获取方法对象
		Method method = arg0.getMethod();
		//获取到它的参数列表
		Object[] args = arg0.getArguments();
		Object returnValue = arg0.proceed();
		
		// 获取类名
		String targetName = target.getClass().getName();
		// 获取方法名
		String methodName = method.getName();
		// 携带参数
		String params = Arrays.toString(args);
		String msg = "【环绕通知】:正在调用->" + targetName + "." + methodName + ",携带参数:" + params;
		System.out.println(msg);
		String msg2="【环绕通知】:目标对象所调用的方法的返回值:"+returnValue;
		System.out.println(msg2);
		return returnValue;
	}
	异常通知
	org.springframework.aop.ThrowsAdvice
	出现异常执行系统提示,然后进行处理。价格异常为例
public void afterThrowing( PriceException ex ) {
		System.out.println("价格输入有误,购买失败,请重新输入!!");
	}
	过滤通知(适配器)
	org.springframework.aop.support.RegexpMethodPointcutAdvisor
	处理买书返利的bug
   过滤通知(spring已经为我们提供了)不需要我们继承RegexpMethodPointcutAdvisor
在这里插入代码片
spring-context.xml
 <!-- 目标对象 -->
	<bean class="com.zking.aop.Biz.impl.BookBizImpl" id="bookBiz"></bean>
	<!-- 前置通知 -->
	<bean class="com.zking.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>
    <!-- 后置通知 -->
    <bean class="com.zking.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
    <!-- 环绕通知 -->
    <bean class="com.zking.aop.advice.MyMethodInterceptor" id="myMethodInterceptor"></bean>
    <!-- 异常通知 -->
    <bean class="com.zking.aop.advice.MyThrowsAdvice" id="myThrowsAdvice"></bean>
    <!-- 过滤通知(spring已经为我们提供了) -->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="MyRegexpMethodPointcutAdvisor">
        <property name="advice" ref="myAfterReturningAdvice"></property>
        <!--pattern 正则匹配    .*buy:[.*]任意字符0-n个以buy结尾的方法 -->
        <property name="pattern" value=".*buy"></property>
    </bean>
    
    <!-- 生成代理 (目标对象+通知)-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean">
        <property name="target" ref="bookBiz"></property>
        <!--代理的接口 (代理工厂生产的代理需要实现的接口列表)-->
        <property name="proxyInterfaces">
           <list>
               <value>com.zking.aop.Biz.IBookBiz</value>
           </list>
        </property>
        <property name="interceptorNames">
           <list>
               <value>myMethodBeforeAdvice</value>
<!--                <value>myAfterReturningAdvice</value> -->
               <value>myMethodInterceptor</value>
               <value>myThrowsAdvice</value>
               <value>MyRegexpMethodPointcutAdvisor</value>
           </list>
        </property>
    </bean>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值