提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、AOP是什么?
在运行时,动态的将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。AOP即面向切面编程
aop的作用:在不修改代码的情况下可以达到进行增强( 在不修改源代码情况下,还可以执行其他操作)
优势:减少重复代码
提高开发效率
维护方便
二、AOP(底层原理)----底层使用动态代理
第一种 有接口情况,使用 JDK 动态代
⚫ 创建接口实现类代理对象,增强类的方法
第二种 没有接口情况,使用 CGLIB 动态代理
⚫ 创建子类的代理对象,增强类的方法
三、AOP(JDK 动态代理)
1、使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象
(1)调用 newProxyInstance 方法
方法有三个参数:
第一参数,类加载器:代理类加载,测试类加载器,接口类加载都可
第二参数,增强方法所在的类,这个类实现的接口,支持多个接口—class数组类型
第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分
2、编写 JDK 动态代理代码
(1)创建接口,定义方法
public interface UserDao {
public int add(int a,int b);
public String update(String id);
}
(2)创建接口实现类,实现方法
package com.NS.JDK动态代理;
/**
* 创建JDK动态代理代码
* */
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
System.out.println("add方法执行.....");
return a+b;
}
@Override
public String update(String id) {
System.out.println("update方法执行.....");
return id;
}
}
(3)使用 Proxy 类创建接口代理对象
package com.NS.JDK动态代理;
/**动态代理的作用----便于·在类中添加方法
1.Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
2.可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
3.解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces ={UserDao.class};
UserDaoImpl userDao =new UserDaoImpl();
UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),//类加载器去加载代理对象
interfaces,//动态代理类需要实现的接口,数组性
new UserDaoProxy(userDao));//动态代理方法在执行时,会调用h里面的invoke方法去执行
int result=dao.add(1,2);
System.out.println("result:"+result );
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//目标对象 1.把创建的是谁的代理对象,把谁传递过来
private Object obj;
// 有参构造传递
public UserDaoProxy (Object obj){
this.obj=obj;
}
//增强的逻辑---添加方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("方法之前执行....."+method.getName()
+":传递参数..."+ Arrays.toString(args));
//被增强的方法执行---对象 参数
Object res= method.invoke(obj,args);
//方法之后
System.out.println("方法之后执行....."+obj);
return res;
}
}
四、 AOP(术语)
1、连接点
连接点描述的是程序执行的某个特定位置。如一个类的初始化前、初始化后,或者类的某个方法调用前、调用后、方法抛出异常后等等。一个类或一段程序代码拥有一些具有边界性质的特定点,这些特定点就称为连接点。连接点用来定义在目标程序的哪里通过AOP加入新的逻辑。
通俗理解:连接点就是程序执行的某个特定的位置,如:类开始初始化前、类初始化后、类的某个方法调用前、类的某个方法调用后、方法抛出异常后等。Spring 只支持类的方法前、后、抛出异常后的连接点
2、切入点
上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
通俗理解:切入点是一个连接点的过滤条件
3、通知(增强)
切面在某个具体的连接点采取的行为或行动,称为通知。切面的核心逻辑代码都写在通知中,有人也称之为增强或者横切关注点。通知是切面功能的具体实现,通常是业务代码以外的需求,如日志、验证等,这些被模块化的特殊对象。
.通俗理解:实际增强的逻辑部分
-
前置通知:org.springframework.aop.MethodBeforeAdvice
-
后置通知:org.springframework.aop.AfterReturningAdvice
-
异常通知:org.springframework.aop.ThrowsAdvice
-
该接口没有要实现的方法,需要自定义一个afterThrowing()方法。
-
环绕通知:org.aopalliance.intercept.MethodInterceptor
4、切面
切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义
通俗理解:切面由切点和增强组成,或者只由增强实现。