Hello,明天给各位童鞋们分享Spring AOP,连忙拿出小本子记下来吧!
概述
AOP是aspect-oriented programming的缩写,译为面向切面编程。利用 AOP 能够对业务逻辑的各个局部进行隔离,从而使得 业务逻辑各局部之间的耦合度升高,进步程序的可重用性,同时进步了开发的效率。简略来说,AOP就是不批改源代码在骨干性能外面增加新性能。
底层原理
AOP底层应用了动静代理:在有接口的时候应用JDK 动静代理、在没有接口的时候应用CGLIB字节码动静代理。
JDK动静代理
简介
应用JDK 动静代理须要用到JDK中的Proxy类外面的newProxyInstance办法创立代理对象。办法如下:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
newProxyInstance办法的三个参数阐明:
loader 定义代理类的类加载器
interfaces 代理类要实现的接口列表(能够多个)
h 指派办法调用的处理程序(要加强的性能在这外面实现)
newProxyInstance办法返回一个指定接口的代理类实例。
InvocationHandler接口中有个invoke办法,用于实现加强的性能:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
invoke办法的三个参数阐明:
proxy示意代理对象
method示意被加强的办法
args是办法的参数 若没有则为null
示例代码
代码构造如下:
└─src
└─com └─spring5 JDKProxy.java UserDao.java UserDaoImpl.java
UserDao接口:
public interface UserDao {
int add(int a,int b); String update(String id);
}
UserDaoImpl类:
JDKProxy类:
运行后果:
办法之前执行…add :传递的参数…[1, 2]
I am add…
办法之后执行…com.spring5.UserDaoImpl@355da254
result:3
CGLIB字节码动静代理
简介
应用CGLIB字节码动静代理不受代理类必须实现接口的限度,其底层采纳ASM字节码生成框架。CGLIB动静代理的优缺点:
应用字节码技术生产代理类比JAVA反射效率高
不能对申明为final的办法进行代理,因为其原理是动静生成被代理类的子类
须要实现接口MethodInterceptor,而后重写intercept办法:
Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable;
intercept办法的参数阐明:
- proxy CGLIB生成的代理类实例,也是指标对象的子类,相当于重写父类办法
- method 被代理办法
- args 办法参数
- 为生成的代理类对办法的代理援用
intercept办法返回
另外用到了Enhancer类,它是Cglib中的一个字节码增强器,先调它的setSuperclass()将被代理类设置成父类、再调setCallback函数执行intercept办法,最初调create()生成代理类。
示例代码
代码构造如下:
└─src
└─com └─spring5 CglibProxy.java User.java
User类:
public class User {
public void sleep() { System.out.println("我想睡觉...");}
}
CglibProxy类:
运行后果:
睡觉前脱衣服
我想睡觉…
起床穿衣服
AOP操作
概述
AOP相干的几个术语:
- 连接点
类外面哪些办法能够被加强,这些办法称为连接点
- 切入点
理论被真正加强的办法称为切入点
- 告诉
理论加强的逻辑局部称为告诉,分为前置告诉、后置告诉、盘绕告诉、异样告诉和最终告诉五种类型,其中最终告诉相当于JAVA的finally。
- 切面
把告诉利用到切入点过程
AspectJ
AspectJ不是 Spring 组成部分,是一个独立的AOP 框架,个别把 AspectJ 和 Spirng 框架一起使 用,进行 AOP操作。加强就是代理的意思。
筹备工作
在进行AOP操作的时候须要先引入上面四个Jar包
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aspects-5.2.6.RELEASE.jar
引入包后的所有包如下:
com.springsource.net.sf.cglib-2.2.0.jar
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
- spring-aspects-5.2.6.RELEASE.jar
- commons-logging-1.1.1.jar
- spring-aop-5.2.6.RELEASE.jar
- spring-beans-5.2.6.RELEASE.jar
- spring-context-5.2.6.RELEASE.jar
- spring-core-5.2.6.RELEASE.jar
- spring-expression-5.2.6.RELEASE.jar
AspectJ的切入点表达式相干阐明如下:
- 作用
晓得对哪个类外面的哪个办法进行加强
- 语法
execution([权限修饰符] [返回类型] [类全门路] 办法名称 )
- 示例
基于注解实现
次要步骤
次要步骤如下:
在spring 配置文件中,开启注解扫描
须要在XML中引入context和aop的上下文空间。
应用注解创立 User 和 UserProxy 对象
在加强类下面增加注解 @Aspect
在 spring配置文件中开启生成代理对象
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
开启Aspectj生成对象后,会去代码中扫描@aspect注解
配置不同类型的告诉
在告诉办法下面应用@Before、@AfterReturning、@Around、@AfterThrowing和@After注解,联合切入点表达式配置。
@after是在办法执行之后执行(有异样也执行),@afterReturning是在返回值之后执行(有异样不执行)。
示例代码
代码构造:
User类:
UserProxy类:
Test类:
无异样返回后果:
Around 盘绕之前
前置告诉 before
I am add
Around 盘绕之后
最终告诉 after
后置告诉(返回告诉)afterReturning
有异样时返回后果:
Around 盘绕之前
前置告诉 before
最终告诉 after
异样告诉 afterThrowing
java.lang.ArithmeticException: / by zero
雷同切入点提取
用@Pointcut标签
多个加强类对同一个办法进行加强
用@Order注解设置加强类优先级,数字类型值越小示意优先级越高。
@Component
@Aspect
@Order(1)
public class PersonProxy{ }
齐全注解开发
在启动配置类中增加@EnableAspectJAutoProxy注解:
@Configuration
@ComponentScan(basePackages = { "com.spring5"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
基于配置文件实现
具体步骤
创立加强类和被加强类,创立相干办法
在spring 配置文件中配置两个类对象
在 spring 配置文件中配置AOP
示例代码
代码构造如下:
Student类:
StudentProxy类:
Test类:
bean.xml:
运行后果:
I am before…
I want to buy a book…
I am afterReturn…
好啦,明天的文章就到这里,心愿能帮忙到屏幕前迷茫的你们