- AOP(Aspect Oriented Programming)是面向切面编程。
就是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
前面这官方的理解起来相当困难,简单说 就是在不改变方法原代码的基础上,对方法进行功能增强,本质上是生成了一个新的类,叫做代理类,在这个代理类的方法里,对你要加强的方法,在执行前,执行后添加新的代码或方法,然后方法调用时调用的是加强后的代理类方法 - AOP对程序的扩展方式采用动态代理的方式. (JDK动态代理和Cglib动态代理两种方式)
Spring 动态代理
(1)JDK的动态代理
Proxy类的方法
- Proxy类的静态方法可以创建代理对象
static Object newProxyInstance(ClassLoader loader, Class<?>[]
interfaces, InvocationHandler h)
三个参数
- 参数1:ClassLoader loader 类加载器 , 用来加载代理对象
- 参数2:Class<?>[] interfaces 目标类的字节码对象数组. 因为代理的是接口,需要知道接口中所有的方法
- 参数3:InvocationHandler h 执行句柄, 代理对象处理的核心逻辑就在该接口中
InvocationHandler接口
.InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法
每一个动态代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用,
/**
* proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0
* method:我们所要调用某个对象真实的方法的Method对象
* args:指代代理对象方法传递的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
Proxy的 newProxyInstance方法
Proxy类就是用来创建一个代理对象的类,它提供了很多方法,但是我们最常用的是newProxyInstance方法
这个方法的作用就是创建一个代理类对象,它接收三个参数,我们来看下几个参数的含义:
loader:一个classloader对象,定义了由哪个classloader对象对生成的代理类进行加载
interfaces:一个interface对象数组,表示我们将要给我们的代理对象提供一组什么样的接口,如果我们提供了这样一个接口对象数组,那么也就是声明了代理类实现了这些接口,代理类就可以调用接口中声明的所有方法。
h:一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用。
动态代理中核心的两个接口和类上面已经介绍完了,接下来我们就用实例来讲解下具体的用法
案例
首先我们定义一个接口IStudent
public interface IStudent {
void study();
}
定义一个Student 类,来实现IStudent 接口
import com.qst.dao.IStudent;
public class Student implements IStudent {
@Override
public void study() {
System.out.println("学生上课学习");
}
}
现在我们要定义一个代理类的调用处理程序,每个代理类的调用处理程序都必须实现InvocationHandler接口,代理类如下:
@Test
public void test1(){
//jdk代理 Student 类
final Student student=new Student();
//获取一个类加载器
ClassLoader classLoader=Student.class.getClassLoader();
//获取要代理类的接口,两种方法都可以,一个是自己手动添加,一个是通过方法获得
/* Class [] interfaces=new Class[]{IStudent.class};*/
//获取类实现的所有接口
Class<?>[] interfaces=Student.class.getInterfaces();
//处理器
InvocationHandler handler=new InvocationHandler() {
/**
* proxy:代理类代理的真实代理对象com.sun.proxy.$Proxy0
* method:我们所要调用某个对象真实的方法的Method对象
* args:指代代理对象方法传递的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在真实的对象执行之前我们可以添加自己的操作
System.out.println("before invoke。。。");
Object returnValue= method.invoke(student,args);
//在真实的对象执行之后我们可以添加自己的操作
System.out.println("after invoke。。。");
return returnValue;
}
};
//Proxy类就是用来创建一个代理对象的类,它提供了很多方法,但是我们最常用的是newProxyInstance方法。作用就是创建一个代理类对象
IStudent iStudent= (IStudent) Proxy.newProxyInstance(classLoader,interfaces,handler);
iStudent.study();
}