spring_AOP非注解
来源:互联网 发布:js判断空字符串 编辑:程序博客网 时间:2024/06/05 17:22
1.AOP:全称是Aspect Oriented Programming,即面向切面编程
2.AOP的作用及优势
作用:
在程序运行期间,不修改源码对已有方法进行增强。
优势:
减少重复代码 提高开发效率 维护方便
3.AOP的实现方式,使用动态代理技术.
动态代理的特点
字节码随用随创建,随用随加载。
它与静态代理的区别也在于此。因为静态代理是字节码一上来就创建好,并完成加载。
装饰者模式就是静态代理的一种体现。
动态代理常用的有两种方式
基于接口的动态代理
提供者:JDK官方的Proxy类。
要求:被代理类最少实现一个接口。
public class MyProxy {
public static CustomerService getCustomerServiceImp(final CustomerService cs){
CustomerService object = (CustomerService) Proxy.newProxyInstance(MyProxy.class.getClassLoader(), cs.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
Object object = method.invoke(cs, args);
System.out.println("方法增强了吗");
return object;
}
});
return object;
}
}
基于子类的动态代理
提供者:第三方的CGLib,如果报asmxxxx异常,需要导入asm.jar。
要求:被代理类不能用final修饰的类(最终类)。
public class MyProxyCglib {
public static CustomerService getCglib(){
Enhancer eh = new Enhancer();
//设置父类
eh.setSuperclass(CustomerServiceImpl.class);
//设置回调函数
eh.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("嘿,我是cglib");
Object object = method.invoke(method, arg2);
return object;
}
});
CustomerService object2 = (CustomerService) eh.create();
//返回对象
return object2;
}
在spring中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
4.AOP的相关术语:
Joinpoint(连接点):
所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
Pointcut(切入点):
所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。
Advice(通知/增强):
所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
Introduction(引介):
引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field。
Target(目标对象):
代理的目标对象。
Weaving(织入):
是指把增强应用到目标对象来创建新的代理对象的过程。
spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
Proxy(代理):
一个类被AOP织入增强后,就产生一个结果代理类。
Aspect(切面):
是切入点和通知(引介)的结合。
5. 配置步骤
第一步:把通知类用bean标签配置起来
<!-- 把有公共代码的类也让spring来管理(把通知类也交给spring来管理) -->
<bean id="logger" class="com.itheima.util.Logger"></bean>
第二步:使用aop:config声明aop配置
<!-- aop的配置 -->
<aop:config>
<!-- 配置的代码都写在此处 -->
</aop:config>
第三步:使用aop:aspect配置切面
<!-- 配置切面 :此标签要出现在aop:config内部
id:给切面提供一个唯一标识
ref:引用的是通知类的bean的id
<aop:aspect id="logAdvice" ref="logger">
<!--配置通知的类型要写在此处-->
</aop:aspect>
第四步:使用aop:before配置前置通知
<!-- 用于配置前置通知:指定增强的方法在切入点方法之前执行
method:用于指定通知类中的增强方法名称
ponitcut-ref:用于指定切入点的表达式的引用
-->
<aop:before method="beforePrintLog" pointcut-ref="pt1"/>
第五步:使用aop:pointcut配置切入点表达式
<aop:pointcut expression="execution(public void com.itheima.service.impl.CustomerServiceImpl.saveCustomer())"
id="pt1"/>
6. 切入点表达式说明
execution:
匹配方法的执行(常用)
execution(表达式)
表达式语法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
写法说明:
全匹配方式:
public void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
访问修饰符可以省略
void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
返回值可以使用*号,表示任意返回值
* com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
包名可以使用*号,表示任意包,但是有几级包,需要写几个*
* *.*.*.*.CustomerServiceImpl.saveCustomer()
使用..来表示当前包,及其子包
* com..CustomerServiceImpl.saveCustomer()
类名可以使用*号,表示任意类
* com..*.saveCustomer()
方法名可以使用*号,表示任意方法
* com..*.*()
参数列表可以使用*,表示参数可以是任意数据类型,但是必须有参数
* com..*.*(*)
参数列表可以使用..表示有无参数均可,有参数可以是任意类型
* com..*.*(..)
全通配方式:
* *..*.*(..)
7.<aop:config>
作用:
用于声明开始aop的配置
<aop:aspect>
作用:
用于配置切面。
属性:
id:给切面提供一个唯一标识。
ref:引用配置好的通知类bean的id。
<aop:pointcut>
作用:
用于配置切入点表达式
属性:
expression:用于定义切入点表达式。
id:用于给切入点表达式提供一个唯一标识。
<aop:before>
作用:
用于配置前置通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
<aop:after-returning>
作用:
用于配置后置通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
<aop:after-throwing>
作用:
用于配置异常通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
<aop:after>
作用:
用于配置最终通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
<aop:around>
作用:
用于配置环绕通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
通知的类型
类型说明
<!-- 配置通知的类型
aop:before:
用于配置前置通知。前置通知的执行时间点:切入点方法执行之前执行
aop:after-returning:
用于配置后置通知。后置通知的执行时间点:切入点方法正常执行之后。它和异常通知只能有一个执行
aop:after-throwing
用于配置异常通知。异常通知的执行时间点:切入点方法执行产生异常后执行。它和后置通知只能执行一个。
aop:after
用于配置最终通知。最终通知的执行时间点:无论切入点方法执行时是否有异常,它都会在其后面执行。
aop:around
用于配置环绕通知。他和前面四个不一样,他不是用于指定通知方法何时执行的。
-->
<aop:before method="beforePrintLog" pointcut-ref="pt1"/>
<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"/>
<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"/>
<aop:after method="afterPrintLog" pointcut-ref="pt1"/>
<aop:around method="aroundPringLog" pointcut-ref="pt1"/>
环绕通知的特殊说明
/**
* 环绕通知
* 它是spring框架为我们提供的一种可以在代码中手动控制增强部分什么时候执行的方式。
* 问题:
* 当我们配置了环绕通知之后,增强的代码执行了,业务核心方法没有执行。
* 分析:
* 通过动态代理我们知道在invoke方法中,有明确调用业务核心方法:method.invoke()。
* 我们配置的环绕通知中,没有明确调用业务核心方法。
* 解决:
* spring框架为我们提供了一个接口:ProceedingJoinPoint,它可以作为环绕通知的方法参数
* 在环绕通知执行时,spring框架会为我们提供该接口的实现类对象,我们直接使用就行。
* 该接口中有一个方法proceed(),此方法就相当于method.invoke()
*/
public void aroundPringLog(ProceedingJoinPoint pjp){
try {
System.out.println("前置通知:Logger类的aroundPringLog方法记录日志");
pjp.proceed();
System.out.println("后置通知:Logger类的aroundPringLog方法记录日志");
} catch (Throwable e) {
System.out.println("异常通知:Logger类的aroundPringLog方法记录日志");
e.printStackTrace();
}finally{
System.out.println("最终通知:Logger类的aroundPringLog方法记录日志");
}
}
阅读全文
0 0
- spring_AOP非注解
- spring_AOP注解入门
- spring_aop
- spring_AOP
- Spring_aop
- Spring_AOP
- Spring_AOP
- Jeecg中通过Spring_AOP+注解方式实现日志的管理
- Spring_AOP 概念
- Spring_aop配置
- 3、spring_aop
- Spring_aop学习
- SpringMVC 实例 --非注解
- SpringMVC 实例 --非注解
- springmvc(非注解)
- Spring_AOP原理解析
- Spring_aop切面编程
- Spring_AOP原理解析
- centOS 启动异常处理
- 11.13 DOM模型
- 51nod 1575 Gcd and Lcm
- HTML签名生成图片+可加水印
- composer 安装扩展包
- spring_AOP非注解
- Python中的with...as的用法
- LeetCode 141. Linked List Cycle && 142. Linked List Cycle II
- AngularJS服务
- 11.13 学习心得
- linux了解
- Android Material Design系列之夜间模式
- 笔记
- Java Web笔记(六)