AOP面向切面编程之spring AOP

一、Spring AOP
1、Spring AOP的两种实现方式

1.基于xml的Spring AOP开发
2.基于注解的Spring AOP开发

2.引入的jar包

spring-aop-4.3.3.RELEASE.jar,
aspectjweaver-1.8.5.jar
aspectjrt-1.8.5.jar

二、基于xml的Spring AOP开发

(1)创建applicationContext-xml-aop.xml,引入aop命名空间和xsd文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:aop="http://www.springframework.org/schema/aop"
         http://www.springframework.org/schema/aop
         https://www.springframework.org/schema/aop/spring-aop.xsd
 ">
</beans>

(2)在xml文件中将业务bean注入

<bean id="bankService" class="springboot.aop.xml.BankServiceImpl">
</bean>
<bean id="loggerAspect" class="springboot.aop.xml.LoggerAspect">
</bean>

(3)使用aop:aspect标签配置代理信息

<aop:config>
  <!--execution(* springboot.aop.xml.*.*(..))解释 第一个*代表匹配所有参数,第二个代表匹配springboot.aop.xml包下的所有类,第三个表示匹配到的类中的所有方法,(..)表示匹配所匹配到方法的所有参数-->
  <aop:pointcut expression="execution(* springboot.aop.xml.*.*(..))" id="loggerPointCut"/>
  <aop:aspect ref="loggerAspect">
   <!-- 前置通知,在被代理方法执行前执行LoggerAspect中的logerBefore()方法-->
   <aop:before method="logerBefore" pointcut-ref="loggerPointCut"/>
   <!-- 后置通知-->
   <aop:after method="logerAfter" pointcut-ref="loggerPointCut"/>
   <!-- 后置返回通知,属性returning的值必须和方法logerAfterReturning返回值的参数名保持一致-->
   <aop:after-returning method="logerAfterReturning" pointcut-ref="loggerPointCut" returning="returnValue"/>
   <!-- 环绕通知-->
   <aop:around method="logerAround" pointcut-ref="loggerPointCut"/>
   <!-- 后置异常通知通知,抛出异常的时候执行-->
   <aop:after-throwing method="loggerAfterThrowing" pointcut-ref="loggerPointCut"  throwing="exception"/>
  </aop:aspect>
 </aop:config>

(4)LoggerAspect中的各种方法

 public void logerBefore(JoinPoint jp) {
  String methodName = jp.getSignature().getName();//可以获取当前执行的方法名
  System.out.println("前置通知: " + methodName + "将要被执行!");
  Object[] args = jp.getArgs();//可以获取参数
  for(Object arg : args) {
   System.out.println("参数为:" + arg);
  }
  
 }
 
 
 public void logerAfter(JoinPoint jp) {
  String methodName = jp.getSignature().getName();
  System.out.println("后置通知: " + methodName + "已经被执行!");
  
  Object[] args = jp.getArgs();
  for(Object arg : args) {
   System.out.println("参数为:" + arg);
  }
 }
 
 public void logerAfterReturning(JoinPoint jp, Object returnValue) {
  String methodName = jp.getSignature().getName();
  System.out.println("后置返回通知 " + methodName + "已经被执行!");
  System.out.println("后置返回通知  返回值:" + returnValue);
 }
 
 /**
  * 环绕通知 需要配置返回值,否則目标方法所有的返回值都为null
  * @param pjp
  * @return
  */
 public Object logerAround(ProceedingJoinPoint pjp) {
  String methodName = pjp.getSignature().getName();
  System.out.println("环绕通知: " + methodName );
  Object[] args = pjp.getArgs();數
  args[0] = "改变参数";
  try {
   Object returnValue = pjp.proceed(args);
   
   System.out.println("环绕通知: " + methodName +“返回值:” + returnValue);
   return new BigDecimal("999999999999999");//可以改变参数的返回值
  } catch (Throwable e) {
   e.printStackTrace();
  }
  return null;
 }
 
 public void loggerAfterThrowing(JoinPoint jp, Exception exception) {
  System.out.println("后置异常通知:" + exception);
 }

(4)被代理类的代码

public class BankServiceImpl implements BankService{

	public BigDecimal transfer( String source, String target,BigDecimal money) {
	  System.out.println(source + "向" + target + "转账:" + money);
	 // throw new RuntimeException("故意出的异常");
	  return new BigDecimal("12345678");
	}
}	

(5)Main类中方法调用

public class Main {
	public static void main(String[] args) {
	ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext-xml-aop.xml");
	BankService bs = ioc.getBean("bankService", BankService.class);
	bs.transfer("你", "我", new BigDecimal("100000000"))
	}
}

(6)分析
调用main方法时,首先创建了一个ioc容器,后面的参数(“applicationContext-xml-aop.xml”)代表的是该容器所对应的文件,然后通过ioc容器调用了getBean方法生成了一个bs对象,然后bs对象调用transfer方法。
执行过程中,因为xml文件中注册了LoggerAspect,所以transfer方法会被截住,执行一系列通知方法。其中后置返回通知方法能够改变方法的参数以及返回值

三、基于注解的Spring AOP开发
1.开发过程
(1)引入aop命名空间和xsd文件(同xml)
(2)在xml中进行配置

 <!-- 自动扫描注入springboot.aop.anno包下的内容-->
<context:component-scan base-package="springboot.aop.anno"></context:component-scan>
 
 <!-- 开启Spring AOP 自动代理 -->
 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

(3)业务类BankServiceImpl加注解@Service(“bankService”),将其注入到IOC容器中
(4)在通知类LoggerAspect中编写代码

//@Aspect:作用是把当前类标识为一个切面供容器读取  
//@Order(0):当有多个通知类时决定优先级,数字越小优先级越高
//@Component:将该类注入到ioc容器
@Aspect
@Order(0)
@Component
public class TrancationAspect {

@Pointcut("execution(* springboot.aop.anno.*.*(..))")
public void logPointCut() {
}
//PointCut封装,封装之后在注解中execution(* springboot.aop.anno.*.*(..))等价于logPointCut()

//@Before("execution(* springboot.aop.anno.*.*(..))")因为PointCut已经被封装,所以本行跟下一行效果相同
@Before("logPointCut()")
public void logerBefore(JoinPoint jp) {
	//AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象
	String methodName = jp.getSignature().getName();
	System.out.println("TrancationAspect 事务前置通知:method: " + methodName + "将要被执行!");
	Object[] args = jp.getArgs();
	for(Object arg : args) {
		System.out.println("=============参数:>" + arg);
	}
}
}

(5)Main类中调用,代码如下

public static void main(String[] args) {
	ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext-anno-aop.xml");
	BankService bs = ioc.getBean("bankService", BankService.class);
	bs.transfer("你", "我", new BigDecimal("100"));
}

2、分析
通过注解的方式进行Spring AOP开发,主要分三步
(1)将业务类以及通知类注入到IOC容器
(2)编写业务类业务代码,在通知类中编写出发通知时的方法
(3)编写主函数出发通知类的通知
(4)执行逻辑跟xml方式一样,只不过是实现方式不同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值