栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

Spring之AOP

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring之AOP

目录

一、AOP概念

AOP解决的问题

AOP中关键性概念 

如何实现AOP

二、AOP使用

准备工作

前置通知

后置通知

​编辑

环绕通知

异常通知

过滤通知(适配器)

 三、总结


一、AOP概念

AOP:即面向切面编程

AOP解决的问题

解决了需求的改变,造成了原有没必要改变的代码,需要去改变它;

比如:书籍的增删改,本身只需要完成增删改即可,这时如果需要添加日志功能,那么需要在原有的代码基础上,去修改添加日志功能,受牵连的方法就三个(add/edit/del)

AOP中关键性概念 

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

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

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

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

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

如何实现AOP

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

二、AOP使用

准备工作

BookBiz.java

package com.maomao.aop.biz;

public interface BookBiz {
	// 购书
	public boolean buy(String userName, String bookName, Double price);

	// 发表书评
	public void comment(String userName, String comments);
}

异常类 PriceException.java

package com.maomao.aop.exception;

public class PriceException extends RuntimeException {

	public PriceException() {
		super();
	}

	public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public PriceException(String message, Throwable cause) {
		super(message, cause);
	}

	public PriceException(String message) {
		super(message);
	}

	public PriceException(Throwable cause) {
		super(cause);
	}
	
}

BookBizImpl.java

package com.maomao.aop.biz.impl;

import com.maomao.aop.biz.BookBiz;
import com.maomao.aop.exception.PriceException;

public class BookBizImpl implements BookBiz {

	public BookBizImpl() {
		super();
	}

	public boolean buy(String userName, String bookName, Double price) {
		// 通过控制台的输出方式模拟购书
		if (null == price || price <= 0) {
			throw new PriceException("book price exception");
		}
		System.out.println(userName + " buy " + bookName + ", spend " + price);
		return true;
	}

	public void comment(String userName, String comments) {
		// 通过控制台的输出方式模拟发表书评
		System.out.println(userName + " say:" + comments);
	}

}

前置通知

         实现org.springframework.aop.MethodBeforeAdvice接口
        买书、评论前加系统日志

MyMethodBeforeAdvice.java

package com.maomao.aop.advice;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.springframework.aop.MethodBeforeAdvice;


public class MyMethodBeforeAdvice implements MethodBeforeAdvice{

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//		目标对象的类名
		String clzName=arg2.getClass().getName();
//		当前调用的方法是
		String methdName=arg0.getName();
//		当前调用方法所传递参数
		String args=Arrays.toString(arg1);
		System.out.println("【系统日志】:"+clzName+"."+methdName+"被调用,传递的参数为:"+args);
		
	}

}

spring-context.xml 


	
	
	
	
	
		
		
		
		
			
				com.maomao.aop.biz.BookBiz
			
		
		
		
			
				myBefore
			
		
	

测试 

package com.maomao.aop.demo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.maomao.aop.biz.BookBiz;

public class Demo1 {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
		BookBiz bean=(BookBiz)context.getBean("bookBiz");
		bean.buy("aa", "abc", 99.9);
		bean.comment("aa", "123123");
	}

}

后置通知

         实现org.springframework.aop.AfterReturningAdvice接口
        买书返利(存在bug)

每调用一次buy方法打印:“[销售返利][时间]返利3元。”

MyAfterReturningAdvice.java

package com.maomao.aop.advice;
 
import java.lang.reflect.Method;
import java.util.Arrays;
 
import org.springframework.aop.AfterReturningAdvice;
 
public class MyAfterReturningAdvice implements AfterReturningAdvice {
	
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
 
		String targetName = target.getClass().getName();
		String methodName = method.getName();
		String params = Arrays.toString(args);
		String msg = "【返利通知:返利3元】:正在调用" + targetName + "." + methodName + ",携带的参数:" + params + ";目标对象所调用的方法的返回值:"
				+ returnValue;
		System.out.println(msg);
	}
}

spring-context.xml 


	

运行结果

 

环绕通知

        org.aopalliance.intercept.MethodInterceptor
        类似拦截器,会包括切入点,目标类前后都会执行代码。

MyMethodInterceptor.java

package com.maomao.aop.advice;
 
import java.lang.reflect.Method;
import java.util.Arrays;
 
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
 
public class MyMethodInterceptor implements MethodInterceptor {
	
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Object target = invocation.getThis();
		Method method = invocation.getMethod();
		Object[] args = invocation.getArguments();
	
		String targetName = target.getClass().getName();
		String methodName = method.getName();
		String params = Arrays.toString(args);
		String msg = "【环绕通知】:正在调用->" + targetName + "." + methodName + ",携带的参数:" + params;
		System.out.println(msg);
		Object returnValue = invocation.proceed();
		String msg2 = "【环绕通知】:目标对象所调用的方法的返回值:" + returnValue;
		System.out.println(msg2);
 
		return returnValue;
	}
 
 
}

 spring-context.xml 


 

异常通知

         org.springframework.aop.ThrowsAdvice
        出现异常执行系统提示,然后进行处理。价格异常为例

MyThrowsAdvice.java

package com.maomao.aop.advice;
 
import org.springframework.aop.ThrowsAdvice;
 
import com.maomao.aop.exception.PriceException;
 
public class MyThrowsAdvice implements ThrowsAdvice {
	public void afterThrowing(PriceException ex ) {
		System.out.println("【异常通知】:价格输入错误,购买失败,请重新购买");
	}
}

  spring-context.xml 


在原来的测试类改价格

Demo1.java

package com.maomao.aop.demo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.maomao.aop.biz.BookBiz;

public class Demo1 {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
//		BookBiz bean=(BookBiz)context.getBean("bookBiz");
		BookBiz bean=(BookBiz)context.getBean("bookProxy");
		bean.buy("aa", "abc", -99.9);
		bean.comment("aa", "123123");
	}

}

 

 

 

过滤通知(适配器)

        org.springframework.aop.support.RegexpMethodPointcutAdvisor
        处理买书返利的bug

	
	
		
		
	
	
	
		
		
		
		
			
				com.maomao.aop.biz.BookBiz
			
		
		
		
			
				MyBefore
				
				MyAfterPlus
				MyMethod
				MyThrows
			
		
	
	

 三、总结

AOP面向切面编程

主要作用:将核心的业务功能与非核心的业务功能进行分离;

        将核心的业务功能写到目标对象中将非核心的业务功能写到通知中

专业名词:通知、连接点、目标对象、切入点、代理、适配器

日常开发通常的应用场景

  事物管理、日志功能

         事物的开启:前置通知

        事物的提交:后置通知

        事物的回滚:异常通知

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1040440.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号