SpringAOP的操作和具体的使⽤⽅法三步⾛(传统⽅法)
什么是SpringAOP?
通俗的话来讲:就是你的已经做好的项⽬,需要给他增加功能,或者在更新迭代的时候,把以前的⽼的程序⾥⾯的⽅法做增强的话,最原始的⼿段是去直接改代码,这样做的感觉是很不友好的,造成代码的侵⼊性。
⽽AOP的思想是,不去动原来的代码,⽽是基于原来代码产⽣代理对象,通过代理的⽅法,去包装原来的⽅法,就完成了对以前⽅法的增强。换句话说,AOP的底层原理就是动态代理的实现。
关于AOP的三个步骤,把他记住了,AOP就不会有问题:
1. 确定⽬标对象(target—>bean) 通俗的来讲就是“谁不⾏了,你要把他交给spring,就是哪个⽅法需要增强,你就把他交给spring。
2. 编写Advice通知⽅法 (增强代码) 就是写增强代码
3. 配置切⼊点和切⾯ 第三点的作⽤就是:让你的增强代码作⽤于你要增强的⽬标对象上
SpringAOP有两种实现⽅式:传统版本和AspectJ。具体操作都能实现业务需求,但是在这⾥还是希望⼤家能使⽤AspectJ,毕竟整体配置起来较为简单、轻量化,⽽且现在企业⼏乎都是AspectJ,传统的⽅法了解⼀下即可。
1、⾸先介绍⼀下传统的⽅式:
传统SpringAOP的Advice编写:
AOP联盟为通知Advice定义了org.aopalliance.aop.Interface.Advice
Spring按照通知Advice在⽬标类⽅法的连接点位置,可以分为5类
(1)前置通知 org.springframework.aop.MethodBeforeAdvice
* 在⽬标⽅法执⾏前实施增强
(2)后置通知 org.springframework.aop.AfterReturningAdvice
* 在⽬标⽅法执⾏后实施增强
(3)环绕通知 org.aopalliance.intercept.MethodInterceptor
* 在⽬标⽅法执⾏前后实施增强
(4)异常抛出通知 org.springframework.aop.ThrowsAdvice
* 在⽅法抛出异常后实施增强
(5)引介通知 org.springframework.aop.IntroductionInterceptor
* 在⽬标类中添加⼀些新的⽅法和属性
简单的说:通知就是增强的⽅式⽅法
遵循aop联盟规范,传统Spring AOP编程的Advice有五种(前置通知、后置通知、环绕通知、异常通知、引介通知) ,
注意:传统SpringAOP的Advice 必须实现对应的接⼝!
那⼩猴就以案例驱动来带你认识⼀下AOP,以环绕通知为例:
【需求】:开发⼀个记录⽅法运⾏时间的例⼦。将⽬标⽅法的运⾏时间,写⼊到log4j的⽇志中。
传统AOP三步⾛:
第⼀步: 引⼊所需依赖:
<!-- spring核⼼依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!—- springaspect集成 -->
<!--这⾥要注意⼀下,这个aspects这个依赖⾥是AOP的相关配置的关键 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- ⽇志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
spring aop应用场景
</dependency>
<!-- spring集成测试 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
引⼊l配置⽂件和⽇志⽂件:
创建⼀个包,随便⾥⾯扔俩类
如果直接在源代码上增加功能的话,那就变成了侵⼊式编程了,所以在不更改源代码的情况下,使⽤AOP进⾏⽅法的更新。使⽤动态代理的代码将对象配置到spring⼯⼚中:
<!--消费者-->
<bean class="com.beijihou.spring.a_proxy.customerService" id="customerService"/>
<!--商品-->
<bean class="com.beijihou.spring.a_proxy.productService" id="productService"/>
第⼆步:编写传统aop的Advice通知类。
⾸先我们新建⼀个包,名字叫oldaop,因为是⽤⽼的传统的⽅法来搞,然后包⾥创建⼀个类,名字叫TimeLogin,意思是运⾏时间。让他实现MethodInterceptor这个接⼝
注意啦,这⾥有坑,就是要选择的是上⾯这个aop的接⼝。
然后实现这个接⼝的⽅法
在此⽅法中,填写如下代码
@Override
//methodInvocation:这个参数指的是代理对象的包装类,⽤来获取代理对象/⽬标对象/⽅法的参数等等...    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//调⽤代理对象原来的⽅法并返回⽅法的返回值
Object proceed = methodInvocation.proceed();
//返回这个返回值,整个代理的过程就结束了
return proceed;
}
即下图:
配置好之后,接下来就可以写你需要创建⼀个⽇志记录器来记录⽅法的运⾏时间:
//⽐如我们要记录⽅法运⾏的时间,并把它保存到⽇志记录器⾥,所以创建⼀个⽇志记录器
private static Logger logger = Logger(TimeLogin.class);
注意这⾥要选择log4j这个包
然后开始在invoke⽅法中添加增强功能的代码:
//⽐如我们要记录⽅法运⾏的时间,并把它保存到本地⽇志⽂件⾥,所以创建⼀个⽇志记录器
private static Logger logger = Logger(TimeLogin.class);
@Override
//methodInvocation:这个指的是代理对象的包装类,⽤来获取代理对象/⽬标对象/⽅法的参数等等...
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//⾸先在⽅法前,添加⼀个记录时间的功能
long beforeTime = System.currentTimeMillis();
//调⽤代理对象原来的⽅法并返回⽅法的返回值
Object proceed = methodInvocation.proceed();
//然后在⽅法之后也添加⼀个记录时间的功能
long afterTime = System.currentTimeMillis();
//最后求出差值便是⽅法使⽤的时间
long useTime = afterTime - beforeTime;
//打印⼀下这个时间:
//Method().getName()  代表哪⼀个⽅法名,修饰⼀下,即什么⽅法运⾏了多长时间
//如果在详细⼀点的话,需要把类名也加上,那么This().getClass().getName()  即什么类的什么⽅法运⾏了多长时间
System.out.This().getClass().getName()+"类的"+Method().getName()+"⽅法使⽤了" + useTime+"毫秒");
//当然上⽅只是打印⼀下,那我们还需要做⽇志的记录到⽂件中
logger.This().getClass().getName()+"类的"+Method().getName()+"⽅法使⽤了" + useTime+"毫秒");
//返回这个返回值,整个代理的过程就结束了
return proceed;
}
}
然后我们去配⼀下log4j.properties⽂件,需要将这段代码添加进去,修改保存位置即可
apache=DEBUG
log4j.appender.A1.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.File=G:/mylog.log
log4j.appender.file.layout.ConversionPattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。