当前位置: 首页 > news >正文

代理(主要是动态)和SpringAOP

代理

  • 静态代理基于继承实现
  • 动态代理是基于接口实现
业务层每次实现转账都需要执行,可以把他们拿出来当成一个切面,自己写出一个代理类,让业务层只执行业务的逻辑,重复的代码代理类来完成,然后调用代理类来执行。
代理类
package com.qcby.utils;import com.qcby.service.AccountService;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//传入目标对象,生成该对象的代理对象,返回。对目标对象的方法进行增强
public class ProxyUtils {//获取代理对象,返回,增强目标对象的方法public static Object getProxy(final AccountService accountService){//使用jdk动态dialing生成代理对象Object proxy = Proxy.newProxyInstance(ProxyUtils.class.getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {//调用代理对象的方法,invoke方法就会去执行public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//目标对象的方法Object result = null;try {//开启事务TxUtils.startTransaction();//目标对象的方法进行增强,作为结果返回result = method.invoke(accountService,args);//事务提交TxUtils.commit();}catch (Exception e){e.printStackTrace();//事务回滚TxUtils.rollback();}finally {//资源关闭TxUtils.close();}return result;}});return proxy;}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Demo2 {@Autowiredprivate AccountService accountService;@Testpublic void run1(){Account account1 = new Account();account1.setName("aaa");Account account2 = new Account();account2.setName("bbb");//创建代理对象AccountService proxy = (AccountService) ProxyUtils.getProxy(accountService);proxy.saveAll(account1,account2);}
}

     AOP

    配置文件形式:(IOC也是用的配置文件形式)
    配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--将目标类配置到spring中--><bean id="userService" class="com.qcby.demo1.UserServiceImpl"/><!--将切面类配置到spring中--><bean id="myXmlAspect" class="com.qcby.demo1.MyXmlAspect"/><!--配置AOP的增强--><aop:config><!--配置切面 = 通知+切入点组成--><aop:aspect ref="myXmlAspect"><!--通用写法--><!--<aop:before method="log" pointcut="execution(public * com.qcby.*.*ServiceImpl.*(..))"/>--><!--前置通知:无论方法成功与否都执行--><!--<aop:before method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>--><!--最终通知:失败成功都执行--><!--<aop:after method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>--><!--后置通知:方法成功执行之后执行--><!--<aop:after-returning method="log" pointcut="execution(public * com.qcby.*.*ServiceImpl.*(..))"/>--><!--异常通知:有异常才执行--><!--<aop:after-throwing method="log" pointcut="execution(public void com.qcby.demo1.UserServiceImpl.save())"/>--><!--环绕通知:目标方法执行前后都执行  执行方法成功与否对执行前的增强不影响(方法执行不成功也执行前置的)--><aop:around method="aroundLog" pointcut="execution(public * com.qcby.demo1.*ServiceImpl.*(..))"/></aop:aspect></aop:config></beans>
    切面类
    package com.qcby.demo1;import org.aspectj.lang.ProceedingJoinPoint;/*定义切面类 = 切入点(表达式)+通知*/
    //在配置文件里配置成切面类=增强的方法(通知)+需要增强的方法(切入点)
    public class MyXmlAspect {/*通知*/public void log(){//发送手机短信//发送邮件、记录日志、事务管理System.out.println("增强的方法执行了....");}public void log1(){//发送手机短信//发送邮件、记录日志、事务管理System.out.println("前置增强的方法执行了....");}public void log2(){//发送手机短信//发送邮件、记录日志、事务管理System.out.println("后置增强的方法执行了....");}/*环绕通知*/public void aroundLog(ProceedingJoinPoint proceedingJoinPoint){try {log1();proceedingJoinPoint.proceed();log2();} catch (Throwable throwable) {throwable.printStackTrace();}}
    }
    测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class Demo1 {@Autowiredprivate UserService userService;/*测试*/@Testpublic void run1(){userService.save();}
    }
    半注解方式
    切面类=通知+切入点(现在的切面类已经在通知上添加了切入点)
    package com.qcby.demo2;import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;@Component  // 把该类交给 IOC 去管理
    @Aspect // 声明是切面类 == <aop:aspect ref="myXmlAspect">
    public class MyAnnoAspect {//@Before(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log1(){System.out.println("前置通知增强的方法执行...");}//@AfterReturning(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log2(){System.out.println("后置通知增强的方法执行...");}//@After(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log3(){System.out.println("最终通知增强的方法执行...");}//@AfterThrowing(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log4(){System.out.println("异常通知增强的方法执行...");}@Around(value = "execution(public * com.qcby.*.*ServiceImpl.*(..))")public void log5(ProceedingJoinPoint proceedingJoinPoint){try {log1();proceedingJoinPoint.proceed();log2();} catch (Throwable throwable) {throwable.printStackTrace();}}
    }
    配置文件
    <!--配置文件中开启自动代理-->
    <aop:aspectj-autoproxy/>
    <!--开启注解扫描-->
    <context:component-scan base-package="com.qcby" />
    测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class Demo2 {@Autowiredprivate AccountService accountService;@Testpublic void run1(){accountService.save();}
    }
    纯注解形式
    配置类
    @Configuration  // 配置类
    @ComponentScan(value = "com.qcby")  // 扫描包
    @EnableAspectJAutoProxy  // 开启自动代理 == <aop:aspectj-autoproxy/>
    public class SpringConfig {
    }
    切面类
    与半注解形式一样
    测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfig.class)
    public class Demo2 {@Autowiredprivate AccountService accountService;@Testpublic void run1(){accountService.save();}
    }
    出现异常时:前置方法,最终方法,异常方法都会执行

    相关文章:

  1. 泰迪杯特等奖案例深度解析:基于多模态融合与小样本学习的工业产品表面缺陷智能检测系统
  2. Latex单栏环境下如何设置表格和图片不独占一栏
  3. 12 分钟讲解所有 JavaScript 库/模块[译]
  4. 曝光融合(Exposure Fusion)
  5. java后端学习
  6. 【记录】Windows|竖屏怎么调整分辨率使横竖双屏互动鼠标丝滑
  7. 51单片机的lcd12864驱动程序
  8. uniapp-商城-57-后台 新增商品(弹窗属性数据添加父级)
  9. 虚拟机在挂起恢复后时间漂移问题
  10. 吉客云数据集成到金蝶云星空的最佳实践
  11. HTML常用标签用法全解析:构建语义化网页的核心指南
  12. 工具:shell命令提示符自定义之显示GIT当前分支
  13. WebGL2光照效果
  14. 龙芯新一代国产服务器CPU及产品闪耀信创大会,助力信创与智算新突破
  15. SpringBoot3.4.5下Lombok的@Data注解不生效,解决方案
  16. 数据科学和机器学习的“看家兵器”——pandas模块 之六
  17. 【漫话机器学习系列】261.工具变量(Instrumental Variables)
  18. 《AI大模型应知应会100篇》第66篇:用大模型 + 向量数据库构建你的个性化知识库系统(附实战代码)
  19. Java 21 + Spring Boot 3.5:AI驱动的高性能框架实战
  20. 【漫话机器学习系列】262.交叉项(Interaction Term)
  21. 湖南4个县市区被确定为野生蘑菇中毒高风险区:中毒尚无特效解毒药
  22. 魔都眼|锦江乐园摩天轮“换代”开拆,新摩天轮暂定118米
  23. 普京召开俄乌谈判筹备会议,拉夫罗夫、绍伊古等出席
  24. 外企聊营商|威能集团:公平环境增“暖”意
  25. 基金经理调仓引发大金融板块拉升?公募新规落地究竟利好哪些板块
  26. 陕西宁强县委书记李宽任汉中市副市长