SpringAOP之JDK动态代理
一.什么是AOP?
AOP简介
AOP的全称是Aspect-Oriented Programming,即面向切面编程(也称面向方面编程)。它是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编程方式。
AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,采用传统的OOP思想显然是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,它只是OOP的延伸和补充。
AOP术语
Aspect:封装的用于横向插入系统功能(如事务、日志等)的类
Joinpoint:在程序执行过程中的某个阶段点
Pointcut:切面与程序流程的交叉点,即那些需要处理的连接点
Proxy(代理):将通知应用到目标对象之后,被动态创建的对象
Weaving(织入):将切面代码插入到目标对象上,从而生成代理对象的过程。
二.动态代理
1.jdk动态代理
JDK动态代理是通过java.lang.reflect.Proxy 类来实现的,我们可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。
类和工具包
控制台打印输出
UserDao.java
package com.itheima.jdk;
/**
* 该类为接口类
* */
public interface UserDao {
/*添加方法,删除方法*/
public void addUser();
public void deleteUser();
}
UserDaoImpl.java
package com.itheima.jdk;
/**
*该类为接口实现类
* */
public class UserDaoImpl implements UserDao{
/*继承接口UserDao,并实现UserDao内的方法*/
@Override
public void addUser() {
System.out.println("添加用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
MyAspect.java
package com.itheima.aspect;
/**
* 该类为切面类
* 并在该类中定义一个模拟检查的方法,和一个模拟记录日志的方法
* 用这两个方法,表示切面的通知
* */
public class MyAspect {
//模拟权限检查
public void check_Permissions() {
System.out.println("模拟权限检查");
}
//模拟记录日日志
public void log() {
System.out.println("模拟记录日志");
}
}
JdkProxy.java
package com.itheima.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.itheima.aspect.MyAspect;
/**
* Jdk代理类,该类实现InvocationHandler接口
* 并编写代理方法
* 在代理方法中需要通过Proxy类实现动态代理
* */
public class JdkProxy implements InvocationHandler {
//声明接口类接口
public UserDao userDao;
//创建代理方法
public Object createProxy(UserDao userDao) {
this.userDao = userDao;
//获取类加载器
ClassLoader classLoader = JdkProxy.class.getClassLoader();
//创建类数组,得到接口类的方法
Class[] clazz = userDao.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader, clazz, this);
}
/**
* 所有动态代理类的方法调用,都交给invoke()方法去处理
* proxy被代理对象
* method 将要被执行方法的信息(反射)
* args执行方法时所需参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//声明切面
MyAspect myAspect = new MyAspect();
//调用模拟权限检查
myAspect.check_Permissions();
//调用方法,传入参数,并反射
Object obj = method.invoke(userDao, args);
//模拟记录日志
myAspect.log();
return obj;
}
}
JdkTest.java
package com.itheima.jdk;
/**
* 该类为测试类
* */
public class JdkTest {
public static void main(String[] args) {
//创建代理对象
JdkProxy jdkProxy = new JdkProxy();
//创建被代理目标对象
UserDao userDao = new UserDaoImpl();
//从代理对象中,获取增强后的被代理目标对象
UserDao userDao2 =(UserDao) jdkProxy.createProxy(userDao);
//执行方法
userDao2.addUser();
userDao2.deleteUser();
}
}
实现效果