做词频分析的网站,ue4培训,梵客装饰公司官网,网站排名软件多浏览器这里写目录标题 jdk动态代理例子CGlib动态代理例子手写spring中的事务部分自定义注解版aop实现方式 Spring的两大重点#xff0c;IOC和AOP#xff0c;今天我们就来学AOP#xff0c;众所周知AOP的底层是动态代理#xff0c;让我们看一下这两种动态代理的区别。
例子#x… 这里写目录标题 jdk动态代理例子CGlib动态代理例子手写spring中的事务部分自定义注解版aop实现方式 Spring的两大重点IOC和AOP今天我们就来学AOP众所周知AOP的底层是动态代理让我们看一下这两种动态代理的区别。
例子 我们常常使用aop切面编程打印日志但是他的底层是什么呢我们常常看到的是封装好的注解并不知道他的底层是如何实现的。 那我们下边先看手动调用动态代理实现执行方法前后打印日志。
jdk动态代理例子 客户端首先调用代理对象的方法
CalculatorProxy类
package AOP.Proxy;import AOP.service.Calculator;
import AOP.util.Util;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;/*** BelongsProject: JAVAtest* BelongsPackage: AOP.Proxy* Author: GuoYuan.Zhao* Description: 描述什么人干什么事儿* CreateTime: 2024-01-24 14:47* Version: 1.0*/public class CalculatorProxy {//必须要有接口如果没有接口不能使用这种方式是用jdk提供的reflect 包下边的类但是//生产环境中我不能保证每个类都有具体的接口所有有第二中方式cglib//两种动态代理的方式一种是JDK 一种是cglibpublic static Calculator getCalculator( final Calculator calculator){//获取被代理对象的类加载器ClassLoader loader calculator.getClass().getClassLoader();Class?[] interfaces calculator.getClass().getInterfaces();InvocationHandler handler new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result null;try{System.out.println(method.getName()方法开始执行参数列表是 Arrays.asList(args));result method.invoke(calculator,args);System.out.println(method.getName()方法结束执行参数列表是 result);}catch (Exception e){System.out.println(method.getName()方法抛出异常e.getMessage());}finally {System.out.println(method.getName()方法执行结束over);}
//return result;}};Object instance Proxy.newProxyInstance(loader, interfaces, handler);return (Calculator) instance;}Calculator接口// //获取被代理对象的类加载器
// ClassLoader loader calculator.getClass().getClassLoader();
//
// Class?[] interfaces calculator.getClass().getInterfaces();
// InvocationHandler handler new InvocationHandler() {
// Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object result null;
// try{System.out.println(method.getName()方法开始执行参数列表是 Arrays.asList(args));
// Util.start(method,args);
// result method.invoke(calculator,args);System.out.println(method.getName()方法开始执行参数列表是 result);
// Util.stop(method,result);
// }catch (Exception e){System.out.println(method.getName()方法抛出异常e.getMessage());
// Util.logExpection(method,e);
// }finally {System.out.println(method.getName()方法执行结束over);
//
// Util.logFinally(method);
// }// return result;
// }
// };
// Object instance Proxy.newProxyInstance(loader, interfaces, handler);
// return (Calculator) instance;
// }MyCalculator类// //获取被代理对象的类加载器
// ClassLoader loader calculator.getClass().getClassLoader();
//
// Class?[] interfaces calculator.getClass().getInterfaces();
// InvocationHandler handler new InvocationHandler() {
// Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object result null;
// try{System.out.println(method.getName()方法开始执行参数列表是 Arrays.asList(args));
// Util.start(method,args);
// result method.invoke(calculator,args);System.out.println(method.getName()方法开始执行参数列表是 result);
// Util.stop(method,result);
// }catch (Exception e){System.out.println(method.getName()方法抛出异常e.getMessage());
// Util.logExpection(method,e);
// }finally {System.out.println(method.getName()方法执行结束over);
//
// Util.logFinally(method);
// }// return result;
// }
// };
// Object instance Proxy.newProxyInstance(loader, interfaces, handler);
// return (Calculator) instance;}
public interface Calculator {public Integer add(Integer i,Integer j) throws NoSuchMethodException;public Integer div(Integer i,Integer j);public Integer mul(Integer i,Integer j);public Integer sub(Integer i,Integer j);}
package AOP.service;import AOP.util.Util;
import org.springframework.stereotype.Service;import java.lang.reflect.Method;/*** BelongsProject: JAVAtest* BelongsPackage: AOP.service* Author: GuoYuan.Zhao* Description: 描述什么人干什么事儿* CreateTime: 2024-01-24 14:15* Version: 1.0*/Service
public class MyCalculator implements Calculator{Overridepublic Integer add(Integer i, Integer j) throws NoSuchMethodException {//11111
// System.out.println(add方法开始执行参数是i___j);
// int result ij;
// System.out.println(add方法结束执行结果是result);
// return result;//22222// Method add MyCalculator.class.getMethod(add, Integer.class, Integer.class);
// Util.start(add,i,j);
// Integer result ij;
// Util.stop(add,result);
// return result;//333333Integer result ij;return result;}Overridepublic Integer div(Integer i, Integer j) {System.out.println(div方法开始执行参数是i___j);Integer result i/j;System.out.println(div方法结束执行结果是result);return result;}Overridepublic Integer mul(Integer i, Integer j) {System.out.println(mul方法开始执行参数是i___j);int result i*j;System.out.println(mul方法结束执行结果是result);return result;}Overridepublic Integer sub(Integer i, Integer j) {System.out.println(sub方法开始执行参数是i___j);Integer result i-j;System.out.println(sub方法结束执行结果是result);return result;}
}
客户端 主函数{Calculator calculator CalculatorProxy.getCalculator(new MyCalculator());calculator.add(1,1);saveProxyClass(E:\\zy\\TGB-zgy-2022\\MiMust\\MiDesignDemo\\JAVAtest\\NormalTest1\\demo\\src);}public static void saveProxyClass(String path) throws IOException {byte[] $proxy1s ProxyGenerator.generateProxyClass($Proxy1, MyCalculator.class.getInterfaces());FileOutputStream out new FileOutputStream(new File(path $Proxy1.class));out.write($proxy1s);}
最后可以看到代理类 这个类里边有 我的目标方法其实客户端调用的就是这个方法 然后h就是我们上边那个匿名内部类的对象
CGlib动态代理例子
CglibFactory类
public class CglibFactory implements MethodInterceptor {public CglibFactory(MyCalculatorCGlib target) {}Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(执行方法 method.getName());Object result methodProxy.invokeSuper(o, objects);//这里实现将返回值字符串变为大写的逻辑
// if(result ! null) {
// result ((String) result).toUpperCase();
// }System.out.println(执行方法完毕结果是result);return result;}public MyCalculatorCGlib myCglibCreator() {System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,E:\\zy\\TGB-zgy-2022\\MiMust\\MiDesignDemo\\JAVAtest\\NormalTest1\\demo\\src);Enhancer enhancer new Enhancer();//将目标类设置为父类cglib动态代理增强的原理就是子类增强父类,cglib不能增强目标类为final的类//因为final类不能有子类enhancer.setSuperclass(MyCalculatorCGlib.class);//设置回调接口,这里的MethodInterceptor实现类回调接口而我们又实现了MethodInterceptor,其实//这里的回调接口就是本类对象,调用的方法其实就是intercept()方法enhancer.setCallback(this);//create()方法用于创建cglib动态代理对象return (MyCalculatorCGlib) enhancer.create();}
}MyCalculatorCGlib类
public class MyCalculatorCGlib {public Integer add(int i, int j) {Integer result ij;return result;}public void doSecond() {
// System.out.println(doSecond()方法);}}客户端 MyCalculatorCGlib target new MyCalculatorCGlib();
// System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,E:\\zy\\TGB-zgy-2022\\MiMust\\MiDesignDemo\\JAVAtest\\NormalTest1\\demo\\src);MyCalculatorCGlib proxy new CglibFactory(target).myCglibCreator();Integer result proxy.add(1,1);按照上边的思路说完上边两种代理方式我们下边来说如何使用这种方式手写事务呢
手写spring中的事务
首先从原理分析事务的原理就是当sql出现问题的时候数据回滚为原来的样子具体他们是通过spring中的DataSourceTransactionManager实现的在sql执行前开启事务事务然后执行sql如果正常就提交事务如果不正常就回滚事务。 这就是大概得逻辑是不是就像上边打印日志一样在执行方法前进行一些操作在执行方法后进行一些操作。 public class Main {public static void main(String[] args) {
// TransactionManager transactionManager new SimpleTransactionManager();
// TransactionProxyFactory factory new TransactionProxyFactory(transactionManager);
// MyService service factory.createProxy(new MyService());
// service.doSomething(); // 这个调用将被代理拦截并处理事务MyService myService new MyServiceImpl();TransactionManager transactionManager new SimpleTransactionManager();DataSourceTransactionManager dataSourceTransactionManager new DataSourceTransactionManager();HikariDataSource dataSource new HikariDataSource();dataSource.setDriverClassName(com.mysql.cj.jdbc.Driver);dataSource.setJdbcUrl(jdbc:mysql://127.0.0.1:3306/zipkin?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai);dataSource.setUsername(root);dataSource.setPassword(123456);dataSourceTransactionManager.setDataSource(dataSource);transactionManager.setDataSourceTransactionManager(dataSourceTransactionManager);// 创建代理对象MyService proxy TransactionalInvocationHandler.createProxy(myService, transactionManager, MyService.class);// 调用代理对象的方法这将触发事务管理proxy.doSomething();}
}
Service
public interface MyService {// Transactionalpublic void doSomething() ;
}
Service
public class MyServiceImpl implements MyService {Overridepublic void doSomething() {try {System.out.println(我真的要执行sql语句);int i 1/0;} catch (ArithmeticException e) {// 处理算术异常例如记录日志或返回错误消息throw new RuntimeException(An arithmetic operation has failed, e);}}
}Component
public interface TransactionManager {TransactionStatus beginTransaction();void commitTransaction(TransactionStatus transactionStatus);void rollbackTransaction(TransactionStatus transactionStatus);public void setDataSourceTransactionManager(DataSourceTransactionManager dataSourceTransactionManager) ;}Component
public class SimpleTransactionManager implements TransactionManager {private boolean isActive false;Overridepublic void setDataSourceTransactionManager(DataSourceTransactionManager dataSourceTransactionManager) {this.dataSourceTransactionManager dataSourceTransactionManager;}private DataSourceTransactionManager dataSourceTransactionManager new DataSourceTransactionManager();Overridepublic TransactionStatus beginTransaction() {if (isActive) {throw new IllegalStateException(Transaction already active);}// 模拟事务开始逻辑在实际应用中这里会涉及到数据库连接的获取、设置隔离级别等操作TransactionStatus transaction dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());isActive true;System.out.println(开启事务了);return transaction;}Overridepublic void commitTransaction(TransactionStatus transactionStatus) {if (!isActive) {throw new IllegalStateException(No active transaction);}// 模拟事务提交逻辑dataSourceTransactionManager.commit(transactionStatus);isActive false;System.out.println(提交事务了);}Overridepublic void rollbackTransaction(TransactionStatus transactionStatus) {if (!isActive) {throw new IllegalStateException(No active transaction);}// 模拟事务回滚逻辑dataSourceTransactionManager.rollback(transactionStatus);isActive false;System.out.println(回滚事务了);}
}public class TransactionalInvocationHandler implements InvocationHandler {Autowiredprivate final Object target;Autowiredprivate final TransactionManager transactionManager;public TransactionalInvocationHandler(Object target, TransactionManager transactionManager) {this.target target;this.transactionManager transactionManager;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Exception {TransactionStatus transactionStatus null;try {transactionStatus transactionManager.beginTransaction();Object result method.invoke(target, args);transactionManager.commitTransaction(transactionStatus);return result;} catch (Exception e) {transactionManager.rollbackTransaction(transactionStatus);throw e;}}public static T T createProxy(T target, TransactionManager transactionManager, ClassT interfaceType) {return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(),new Class?[]{interfaceType},new TransactionalInvocationHandler(target, transactionManager));}
}运行结果
部分自定义注解版aop实现方式 自定义注解 MyTransactionAnnotation
Target({ElementType.TYPE, ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
public interface MyTransactionAnnotation {
}
MyTransaction类
Component
Slf4j
public class MyTransaction {Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;/*** 开启事务并配置默认的事务传播机制* return*/public TransactionStatus begin(){TransactionStatus transaction dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());log.info(事务开启成功);return transaction;}/*** 事务提交* param transaction*/public void commit(TransactionStatus transaction){log.info(事务提交成功);dataSourceTransactionManager.commit(transaction);}/*** 事务回滚* param transaction*/public void rollback(TransactionStatus transaction){log.info(事务回滚成功);dataSourceTransactionManager.rollback(transaction);}
}
MyTransactionAop类
Slf4j
Aspect
Component
public class MyTransactionAop {Autowiredprivate MyTransaction myTransaction;Around(value annotation(com.transaction.annotation.MyTransactionAnnotation))public Object myTransactionAop(ProceedingJoinPoint joinPoint){log.info(进入到事务aop, 准备开启事务);TransactionStatus transactionStatus myTransaction.begin();try {log.info(准备执行目标方法);// 执行目标方法Object object joinPoint.proceed();log.info(目标方法执行完毕准备提交);// 执行方法完毕提交事务并返回myTransaction.commit(transactionStatus);return object;}catch (Throwable throwable) {log.error(目标函数异常手动回滚);// 目标函数异常手动回滚myTransaction.rollback(transactionStatus);return 目标函数异常;}}
}
TestController类
RestController
Slf4j
public class TestController {GetMapping(test_transaction)MyTransactionAnnotationpublic String testTransaction(RequestParam(value name) String name){// int i 1/0;return name;}
}SpringBootApplication
EnableTransactionManagement
public class HbzTransactionApplication {public static void main(String[] args) {SpringApplication.run(HbzTransactionApplication.class, args);}
}
application.yml文件
server:port: 9001servlet:context-path: /test
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/zipkin?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghaiusername: rootpassword: 123456总结当我们大概了解这个AOP的思想以后再去看源码发现都离不开动态代理那就是离不开回调反射