spring源码,AOP的使用

1.AOP是什么

网络上很多解释,本文不在赘述,大致意思就好比,比如你一个月前开发了一个代码,功能就是一个除法功能,而现在,你想在原有除法功能基础上,记录传入的参数(除数,被除数)到数据库,并且在除法功能完成后,记录一下返回值到数据库。按照以前的逻辑是需要到这个除法功能里面,修改原有代码。当然,这个除法功能相对比较简单,修改原有代码不复杂,但是实际生产上的业务肯定是比这个复杂的多,改代码的风险也是不可预计的。在设计模式有一种原则就是开闭原则,对修改关闭,对扩展开放,也是为了规避这一风险,所以spring的Aop很好的做到了这一点。

2.如何使用AOP

引入spring和springAop还有junit的相关jar包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>SpringDemo</groupId>
	<artifactId>SpringDemo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.0.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>5.0.4.RELEASE</version>
		</dependency>
	</dependencies>
</project>

 定义配置类

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.erwan.cap12.Bean")
public class Cap12MainConfigAop {
	@Bean
	public Calculator calculator() {
		return new Calculator();
	}

	@Bean
	public CalculatorAop calculatorAop() {
		return new CalculatorAop();
	}
}

其中EnableAspectJAutoProxy注解就是开启AOP功能

//原有代码,提供除法功能的类


public class Calculator {
	public int div(final int i, final int j) {
		System.out.println("--------");
		return i / j;
	}

}

定义一个切面类,来扩展Calculator

@Aspect
public class CalculatorAop {

	@Around("pointCut()")
	public Object AroundCalculator(final ProceedingJoinPoint proceedingJoinPoint)
 throws Throwable {
		System.out.println("@Around:执行目标方法之前...");
		Object obj = proceedingJoinPoint.proceed();// 相当于开始执行div
		System.out.println("@Arountd:执行目标方法之后...");
		return obj;
	}

	@Before("pointCut()")
	public void logBefore(final JoinPoint joinPoint) {
		System.out.println("div开始前" + Arrays.asList(joinPoint.getArgs()));
	}

	@After("pointCut()")
	public void logEnd(final JoinPoint joinPoint) {
		System.out.println("div开始后" + Arrays.asList(joinPoint.getArgs()));
	}

	@AfterThrowing(value = "pointCut()", throwing = "ex")
	public void logException(final Exception ex) {
		System.out.println("div发生异常" + ex.getMessage());
	}

	@AfterReturning(value = "pointCut()", returning = "result")
	public void logReturn(final Object result) {
		System.out.println("div返回值" + result);
	}

	@Pointcut("execution(public * com.erwan.cap12.Bean.Calculator.*(..))")
	public void pointCut() {

	}
}

测试类:

@Test
public void cap12() {
  AnnotationConfigApplicationContext context = new 
  AnnotationConfigApplicationContext(Cap12MainConfigAop.class);
  Calculator bean = context.getBean(Calculator.class);
  bean.div(4, 2);
}

测试结果如下:
@Around:执行目标方法之前...
div开始前[4, 2]
Calculator自己运行的div
@Arountd:执行目标方法之后...
div开始后[4, 2]
div返回值2
		

所以使用aop就以下三步

1,将业务逻辑组件和切面类都加入到容器中, 告诉spring哪个是切面类(@Aspect)

  2,在切面类上的每个通知方法上标注通知注解, 告诉Spring何时运行(写好切入点表达式,参照官方文档)

  3,开启基于注解的AOP模式  @EableXXXX

 

SpringAOP可以应用5种类型的通知:

1.前置通知(Before):在目标方法被调用之前调用通知功能。

2.后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么。

3.返回通知(After-returning):在目标方法成功执行之后调用通知。

4.异常通知(After-throwing):在目标方法抛出异常后调用通知。

5.环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
其中环绕通知比较特殊,他可以在注解的方法体(AroundCalculator)定义是否执行目标方法,如果不执行,则After 和After-returning则不生效,他也可以在捕捉到异常后,重新执行目标方法(div),功能比较强大

其中@Pointcut就是定义需要拦截或者说增强的目标类和目标类的方法,其中 Calculator.*(..)代表 Calculator类的所有方法就是增强所有方法的调用。

使用JoinPoint可以拿到相关的内容, 比如方法名,  参数

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在搭建spring项目时通常需要这些jar包 commons-logging-1.1.3.jar spring-aop-4.0.6.RELEASE.jar spring-beans-4.0.6.RELEASE.jar spring-context-4.0.6.RELEASE.jar spring-core-4.0.6.RELEASE.jar spring-expression-4.0.6.RELEASE.jar 在使用spring额外功能时 1 需要在xml文件中加入命名空间 可以在spring-framework-4.0.6.RELEASE\docs\spring-framework-reference\html 中搜索关键字查找配置 2 加入需要的jar包(依赖包) 由于没有引入 spring-aop-4.0.6.RELEASE.jar 引起的错误 org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/aop] Offending resource: class path resource [beans.xml] at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70) 由于缺少依赖包 aspectjweaver-1.6.12.jar http://search.maven.org/remotecontent?filepath=org/aspectj/aspectjweaver/1.6.12/aspectjweaver-1.6.12.jar org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around 由于缺少依赖包 aopalliance-1.0.jar org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值