Spring 初识Aop JDK动态代理实现 原理初显
代码语言:txt复制- [一、项目结构](https://cloud.tencent.com/developer)
- [二、具体步骤:](https://cloud.tencent.com/developer)
- [1、创建maven项目 创建好包结构](https://cloud.tencent.com/developer)
- [2、写一个TestDao接口 及实现类](https://cloud.tencent.com/developer)
- [3、 写一个自己的切面类](https://cloud.tencent.com/developer)
- [4、java JDK 实现动态代理](https://cloud.tencent.com/developer)
- [5、JDK 动态代理测试](https://cloud.tencent.com/developer)
- [6、Cglib 实现动态代理](https://cloud.tencent.com/developer)
- [7、Cglib 测试](https://cloud.tencent.com/developer)
- [三、自言自语](https://cloud.tencent.com/developer)
Spring-AOP-理论知识
一、项目结构
二、具体步骤:
1、创建maven项目 创建好包结构
2、写一个TestDao接口 及实现类
代码语言:javascript复制/**
* @version 1.0
* @author: crush
* @date: 2021-03-05 10:26
*/
public interface TestDao {
public void sayHello();
public void save();
public void modify();
public void delete();
}
TestDaoImpl
代码语言:javascript复制/**
* @version 1.0
* @author: crush
* @date: 2021-03-05 10:27
*/
@Repository
public class TestDaoImpl implements TestDao {
public void sayHello() {
System.out.println("武汉加油!中国加油!");
}
public void save() {
System.out.println("保存");
}
public void modify() {
System.out.println("修改");
}
public void delete() {
System.out.println("删除");
}
}
3、 写一个自己的切面类
代码语言:javascript复制/**
* @version 1.0
* @author: crush
* @date: 2021-03-10 11:41
*/
public class MyAspect {
public void check(){
System.out.println("模拟权限处理");
}
public void except(){
System.out.println("模拟异常处理");
}
public void log(){
System.out.println("模拟日志记录");
}
public void monitor(){
System.out.println("性能检测");
}
}
4、java JDK 实现动态代理
代码语言:javascript复制/**
* @version 1.0
* @author: crush
* @date: 2021-03-10 11:47
*
* InvocationHandler是由代理实例的调用处理程序实现的接口。
* 每个代理实例都有一个关联的调用处理程序。
* 在代理实例上调用方法时,该方法调用将被编码并分派到其调用处理程序的invoke方法
*/
public class JdkDynamicProxy implements InvocationHandler {
private Object object;
/**
* @Date 16:24 2021/3/10
*
* 创建代理的方法 建立代理对象和真实对象的代理关系 并返回代理对象
**/
public Object createProxy(Object object){
this.object=object;
// 1、 类加载器
ClassLoader classLoader = JdkDynamicProxy.class.getClassLoader();
// 2、 被代理对象 实现的所有接口
Class[] interfaces = object.getClass().getInterfaces();
// 3、 使用代理类进行增强 返回代理后的对象
/**
* 利用Java的反射技术(Java Reflection),
* 在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象),
* 代理的是接口(Interfaces),不是类(Class),也不是抽象类。
* 在运行时才知道具体的实现,spring aop就是此原理
*/
return Proxy.newProxyInstance(classLoader,interfaces,this);
/**
* newProxyInstance,方法有三个参数:
*
* loader: 用哪个类加载器去加载代理对象
*
* interfaces:动态代理类需要实现的接口
*
* h:动态代理方法在执行时,会调用h里面的invoke方法去执行
*/
}
/**
* @Param [proxy 是被代理的对象,
* method 是将要被执行的方法,
* args 是执行方法 时需要的参数]
* @return java.lang.Object
*
* 处理代理实例上的方法调用并返回结果。在与之关联的代理实例上调用方法时,将在调用处理程序上调用该方法。
*
* invoke 三个参数
* proxy:就是代理对象,newProxyInstance方法的返回对象
*
* method:调用的方法
*
* args: 方法中的参数
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyAspect myAspect = new MyAspect();
myAspect.check();
myAspect.except();
// 在目标类上调用方法并传入参数 相当于调用testDao中的方法
Object obj = method.invoke(object, args);
myAspect.log();
myAspect.monitor();
return obj;
}
}
5、JDK 动态代理测试
代码语言:javascript复制 @Test
public void JdkDynamicTest(){
//创建代理对象
JdkDynamicProxy proxy = new JdkDynamicProxy();
//创建目标对象
TestDao testDao = new TestDaoImpl();
/**
* 从代理对象中获取到增强后的目标对象,
* 该对象是一个被代理的对象
* 它会进入到代理的逻辑方法 invoke 中
*/
TestDao testAdvice = (TestDao) proxy.createProxy(testDao);
// 执行方法
testAdvice.sayHello();
}
6、Cglib 实现动态代理
代码语言:javascript复制/**
* @version 1.0
* @author: crush
* @date: 2021-03-10 16:23
*/
public class CglibDynamicProxy implements MethodInterceptor {
/**
* @Param [o, method, objects, methodProxy]
* 创建代理的方法 生成CGLIB代理对象
* target 是目标对象 需要增强的对象
* 返回目标对象的CGLIB 代理对象
**/
public Object creatProxy(Object target){
// 创建一个动态类对象 即增强类对象
Enhancer enhancer = new Enhancer();
// 确定需要增强的类 设置其父类
//超类 – 要扩展的类或要实现的接口
enhancer.setSuperclass(target.getClass());
// 确定代理逻辑对象为当前对象
// 要求当前对象实现MethodInterceptor 的方法
enhancer.setCallback(this);
// 返回创建的代理对象
return enhancer.create();
}
/**
* @Param [o, method, objects, methodProxy]
* intercept 方法慧再程序执行目标方法时被调用
* proxy 是CGLIB 根据指定父类生成的代理对象
* method 是拦截方法
* args 是拦截方法的参数数组
* methodProxy 是方法代理对象 拥有执行父类的方法 返回代理结果
**/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
MyAspect myAspect = new MyAspect();
myAspect.check();
myAspect.except();
// 在目标类上调用方法并传入参数 相当于调用testDao中的方法
Object obj = methodProxy.invokeSuper(proxy, args);
myAspect.log();
myAspect.monitor();
return obj;
}
}
7、Cglib 测试
代码语言:javascript复制 @Test
public void CglibDynamicProxyTest(){
// 创建代理对象
CglibDynamicProxy proxy = new CglibDynamicProxy();
// 创建目标对象
TestDao testDao = new TestDaoImpl();
//获取增强后的目标对象
TestDao testAdvice = (TestDao) proxy.creatProxy(testDao);
//执行方法
testAdvice.save();
}
三、自言自语
又到一天中课间休息时间拉。