spring的 aop:

aop:面向方面的编程,面向切面的编程,面向横切的编程

        方面就是新的业务功能,把新的方面的功能横切到老的业务的前或后

spring的aop的底层用的是动态代理

       如果目标类有接口就默认用jdk动态代理如果目标类没有接口就用默认cglib动态代理如果目标类有接口且不是final的,还想用cglib动态代理则需要单独配置

spring aop中定义个一套独有的表达式规则用于指定某些业务方法横切新功能

实现spring aop的步骤:

1.创建一个工程 工程是基础

2.导入jar包 spring的功能基础

spring的基础jar

   spring-context.jarspring-core.jarspring-beans.jarspring-expression.jarcommons-logging.jar

spring aop的jar

  spring-aop.jaraspectjweaver-1.8.7.jaraopalliance-1.0.jar

3.创建java类

老的业务类:

     UserDao.java   UserDaoImpl.javaUserService.java    UserServiceImpl.java

新的业务功能/新方面的功能/新的切面的功能,简称为方面/切面
由动态代理创建代理类用于调用接口方法,在接口方法中耦合切面和老业务功能

4.创建spring的配置文件

springaop的xml版本
springaop的annotation版本
无论是xml版本还是注解版本a.实例化老业务和新业务的对象(ioc)b.根据业务需求,设定对象的注入关系(di)c.写spring的特有的表达式规则,用于指定哪些方法需要横切新的功能<aop:XXX>

5.启动spring的容器读取spring的配置文件

6.从spring容器中取出对应的对象备用

xml版本:

新业务功能:

TransactionManager.java

     /*** 此类是一个新功能类,用于给原有业务添加事务处理的功能* 符合单一职责原则,此类只做事务管理* @author Administrator**/public class TransactionManager {/*** 事务的开启* 在前置通知方法中得到目标的参数及其他信息*/public void begin(JoinPoint joinPoint){System.out.print("事务开启");System.out.println("目标方法的参数:"+joinPoint.getArgs()[0].getClass());User user=(User)joinPoint.getArgs()[0];System.out.println("目标方法的参数的值:"+user.getName()+"  "+user.getPassword());System.out.println("目标方法的名称:"+joinPoint.getSignature().getName());System.out.println("调用目标方法的目标对象"+joinPoint.getTarget().getClass());}/*** 事务提交* 在后置通知中得到目标方法的参数及其他信息,还可以得到目标方法的返回值* 注意:如果有JoinPoint joinPoint参数一定要放参数的第一个位置*/public void commit(JoinPoint joinPoint,Object returnValue){System.out.println("事务提交");System.out.println("目标方法的返回值:"+returnValue);}/*** 事务的回滚* 在异常通知中得到目标方法的参数及其他信息,不能得到目标方法的返回值,但能得到异常信息*/public void rollback(JoinPoint joinPoint,Throwable ex){System.out.println("事务回滚");System.out.println("目标方法的异常信息:"+ex.getMessage());}public void finalMethod(JoinPoint joinPoint){System.out.println("finally");}/*** 环绕通知,可以完全替换前4个通知* 用环绕通知有一个最大的好处,能够控制目标方法的执行* @param pjp* @return* @throws Throwable*/public Object around(ProceedingJoinPoint pjp) throws Throwable {Object retVal =null;try{//前置通知System.out.println("前置通知");System.out.println("目标方法的参数:"+pjp.getArgs()[0].getClass());User user=(User)pjp.getArgs()[0];System.out.println("目标方法的参数的值:"+user.getName()+"  "+user.getPassword());System.out.println("目标方法的名称:"+pjp.getSignature().getName());System.out.println("调用目标方法的目标对象"+pjp.getTarget().getClass());retVal = pjp.proceed();//调用目标方法//后置通知System.out.println("后置通知");System.out.println("目标方法的返回值:"+retVal);}catch(Exception e){//异常通知System.out.println("异常通知");e.printStackTrace();}finally{//最终通知System.out.println("最终通知");}        return retVal;}}

spring的配置文件 spring.xml

     <?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:tx="http://www.springframework.org/schema/tx"xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beansfile:///c:/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/aop file:///c:/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/contextfile:///c:/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 老的业务需要实例化对象和注入 --><bean id="userDao" class="com.arno.dao.impl.UserDaoImpl"></bean><bean id="userService" class="com.arno.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean>   <!-- 新的业务/切面实例化对象和注入 /--><bean id="tm" class="com.arno.other.TransactionManager"></bean><!-- spring的独有的配置用于做横切 <aop:config  代表的一个spring的aop配置proxy-target-class="true"  告知spring用cglib生成代理对象proxy-target-class="false" 告知spring用jdk生成代理对象--><aop:config proxy-target-class="true"><!-- <aop:aspect  代表一个切面,一个spring的aop配置可以包含很多个切面 --><aop:aspect id="myTransactionAspect" ref="tm"><!-- <aop:pointcut 切点,且在方法上,由execution表达式限定哪些方法需要切面 ,可以写多个切点 --><aop:pointcut id="businessService"expression="execution(* com.arno.service..*.*(..))"/><aop:pointcut id="businessService1"expression="execution(* com.arno.service..*.*(..)) and args(user)"/><!-- 前置通知/前置功能 aop:before 切在前面pointcut-ref   切在哪个方法上method:切的什么功能arg-names="user"  参数--><!--             <aop:before --><!--                pointcut-ref="businessService" --><!--                 method="begin"/> --><!-- 后置通知/后置功能 --><!--            <aop:after-returning --><!--               pointcut-ref="businessService" --><!--                 method="commit"  --><!--               returning="returnValue"/> --><!-- 异常通知/异常功能 --><!--           <aop:after-throwing --><!--                pointcut-ref="businessService" --><!--                 method="rollback" --><!--              throwing=""/> --><!-- 最终通知 --><!--            <aop:after --><!--                 pointcut-ref="businessService" --><!--                 method="finalMethod"/> --><!-- 环绕通知 --><aop:aroundpointcut-ref="businessService"method="around"/></aop:aspect></aop:config>  </beans>

有关于spring aop中的那些让你发狂的几个概念解释:

切面 aspect:
         切面是一个类,是一个新业务的功能类;切面类中有很多个通知方法比如:TransactionManager.java
连接点 joinpoint:
         连接点就是用代理对象调用目标方法的那句话只有用代理对象调用了目标方法,才有可能把新的业务横切到老的业务上没有连接点,老的业务和新的业务永远不会耦合比如:userService.addUser(new  User());//userService是代理对象
通知 advice:
         通知就是一些功能方法,每个功能就是一个通知,通知存在于切面类中可以有很多个通知的方法比如: begin方法  前置通知commit方法   后置通知rollback方法   异常通知finalMethod方法   最终通知around方法             环绕通知环绕通知能完全替代上面的4个通知,环绕通知能控制目标方法的执行环绕通知和前4中不要同时使用
切入点 pointcut:
             切入点是把切面中的通知,切在什么地方,一般指的老业务中的方法上切入点是且在方法上切入点一般要配合execution表达式和within表达式一同使用
execution表达式
        修饰符   返回值  包名.类名.方法名(参数) throws 异常类型
spring的官方案例:
         § the execution of any public method:匹配任意公有方法公有的 任意返回类型,任意包任意类,任意方法名称,任意参数execution(public * *(..))§ the execution of any method with a name beginning with "set":任意返回类型,任意包,任意类,任意以set开头的方法,任意参数execution(* set*(..))§ the execution of any method defined by the AccountService interface:任意返回类型,com.xyz.service.AccountService接口中的任意方法,任意参数execution(* com.xyz.service.AccountService.*(..))§ the execution of any method defined in the service package:任意返回类型,com.xyz.service包下任意类或接口,任意方法,任意参数execution(* com.xyz.service.*.*(..))§ the execution of any method defined in the service package or a sub-package:任意返回类型,com.xyz.service包及其子包中的任意类,任意方法,任意参数execution(* com.xyz.service..*.*(..))
winthin表达式:
spring官方案例:
         any join point (method execution only in Spring AOP) within the service package:com.xyz.service包中的任意接口或类within(com.xyz.service.*)any join point (method execution only in Spring AOP) within the service package or a sub-package:com.xyz.service包及其子包中的任意类within(com.xyz.service..*)
总结execution控制粒度细,控制到方法 winthin控制粒度粗,控制类

目标对象 targetObject:是老业务类的对象 比如UserServiceImpl的对象

aop代理:

用spring的aop的底层用的是动态代理,aop代理就是用springaop生成的代理对象
织入weaving:把新的功能织入到老的功能上去,引申义就是横切/切入

springaop的注解版本:

TransactionManager.java

/*** 此类是一个新功能类,用于给原有业务添加事务处理的功能* 符合单一职责原则,此类只做事务管理* @author Administrator**/
@Component("tm")
@Aspect
public class TransactionManager {@Pointcut("execution(* com.arno.service..*.*(..))")public void myTransactionPointCut() {}/*** 事务的开启* 在前置通知方法中得到目标的参数及其他信息*///@Before(value="myTransactionPointCut()")public void begin(JoinPoint joinPoint){System.out.print("事务开启");System.out.println("目标方法的参数:"+joinPoint.getArgs()[0].getClass());User user=(User)joinPoint.getArgs()[0];System.out.println("目标方法的参数的值:"+user.getName()+"  "+user.getPassword());System.out.println("目标方法的名称:"+joinPoint.getSignature().getName());System.out.println("调用目标方法的目标对象"+joinPoint.getTarget().getClass());}/*** 事务提交* 在后置通知中得到目标方法的参数及其他信息,还可以得到目标方法的返回值* 注意:如果有JoinPoint joinPoint参数一定要放参数的第一个位置*///@AfterReturning(value="myTransactionPointCut()",returning="returnValue")public void commit(JoinPoint joinPoint,Object returnValue){System.out.println("事务提交");System.out.println("目标方法的返回值:"+returnValue);}/*** 事务的回滚* 在异常通知中得到目标方法的参数及其他信息,不能得到目标方法的返回值,但能得到异常信息*///@AfterThrowing(value="myTransactionPointCut()",throwing="ex")public void rollback(JoinPoint joinPoint,Throwable ex){System.out.println("事务回滚");System.out.println("目标方法的异常信息:"+ex.getMessage());}//@After(value="myTransactionPointCut()")public void finalMethod(JoinPoint joinPoint){System.out.println("finally");}/*** 环绕通知,可以完全替换前4个通知* 用环绕通知有一个最大的好处,能够控制目标方法的执行* @param pjp* @return* @throws Throwable*/@Around(value="myTransactionPointCut()")public Object around(ProceedingJoinPoint pjp) throws Throwable {Object retVal =null;try{//前置通知System.out.println("前置通知");System.out.println("目标方法的参数:"+pjp.getArgs()[0].getClass());User user=(User)pjp.getArgs()[0];System.out.println("目标方法的参数的值:"+user.getName()+"  "+user.getPassword());System.out.println("目标方法的名称:"+pjp.getSignature().getName());System.out.println("调用目标方法的目标对象"+pjp.getTarget().getClass());retVal = pjp.proceed();//调用目标方法//后置通知System.out.println("后置通知");System.out.println("目标方法的返回值:"+retVal);}catch(Exception e){//异常通知System.out.println("异常通知");e.printStackTrace();}finally{//最终通知System.out.println("最终通知");}       return retVal;}
}

spring.xml文件:

     <?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:tx="http://www.springframework.org/schema/tx"xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beansfile:///c:/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/aop file:///c:/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/contextfile:///c:/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 解析@Controller,@Service,@Repository@Component@Resource @Autowired@Qualifier--><context:component-scan base-package="com.arno.dao"></context:component-scan><context:component-scan base-package="com.arno.service"></context:component-scan><context:component-scan base-package="com.arno.other"></context:component-scan><!-- 解析有关于aop的注解@Aspect @Pointcut @Before @AfterReturning  @AfterThrowing @After @Around--><aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy></beans>
一个需求或目的:
老的业务
新的业务
新的业务横切到老的业务上

代理模式能够实现

静态代理:

 用静态代理类方式把老业务和新的业务耦合在一起在编译期间就确认老业务和新业务的耦合关系

动态代理:

jdk的动态代理
     动态生成代理类(由jdk底层来创建,程序员是看不见的)用动态生成的代理类和InvocationHandler接口一起做到老业务和新业务的耦合代理类是在运行期间才出现的,所以叫做动态代理代理类和目标类是兄弟关系
cglib动态代理
     动态生成代理类(由asm.jar来创建,程序员是看不见的)用动态生成的代理类和MethodInterceptor接口一起做到老业务和新业务的耦合代理类是在运行期间才出现的,所以叫做动态代理代理类是目标类的子类

动态代理实现,会把新的业务功能全部横切到老业务的方法的前或后
spring aop解决了把新业务横切到老业务的部分方法的前或后

开发效率
spring aop > 动态代理 >静态代理
执行效率
静态代理 > 动态代理 >spring aop

Sping aop XML与注解方式相关推荐

  1. spring的AOP配置之@注解方式

    AOP配置(注解) spring的AOP概念在spring的AOP配置之XML方式这骗博客中详细介绍了,这篇博客就直接开始介绍AOP配置需要那些注解 AOP注解详解 @Aspect 标志为一个切面类 ...

  2. Dubbo(二):Dubbo 基础配置Xml、注解方式 和 高级特性

    Dubbo的基础配置 Xml方式 注解方式 Dubbo的基础配置使用 启动时检查 超时重连 集群容错 负载均衡配置 结果缓存 服务分组 多版本 只订阅/只注册 异步调用 事件通知 参数回调 本地伪装- ...

  3. AOP通过开启注解方式自动注入值

    注解:EnableDimEnhance package com.comma.teeth.enhance.dim.annotation;import java.lang.annotation.Docum ...

  4. 初步学习Spring Aop使用之注解方式

    前言: 这里就主要演示Spring中Aop使用注解是怎么使用,如果需要了解更多Aop相关概念,可查看相关资料的介绍 一.项目目录 [标记文件为主要文件] 二.各个文件的代码 AopServer.jav ...

  5. SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对照注解方式的优缺点)...

    接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文採用强制的CGLB代理方式 Security ...

  6. Spring IoC和DI XML方式 注解方式 依赖注入 AOP面向切面

    初识Spring框架 时代变迁 原始时代我们用一个jsp搞定一切,但如此开发大型项目时我们遇到了问题,前端美化的代码和后端的代码交织,代码中又有html.js.css样式,又有业务逻辑和数据库访问代码 ...

  7. spring框架:简述AOP的使用(xml方式和注解方式)

    本人小白一枚,欢迎大家一起讨论学习,如有错误,还望大家指教. AOP概述 AOP的概念: AOP,全称Apect Oriented Programming,译为面向切面编程,简单的说它可以帮我们把程序 ...

  8. 第五章 Spring进阶-注解方式实现AOP(1)

    <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 徒弟:师傅,我 ...

  9. 面向切面(AOP)之Spring接口方式 schema配置方式 aspectj注解方式

    一.初识AOP   关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节      1.AOP:Aspect-O ...

  10. Spring AOP XML配置及注解配置

    一.XML配置切面类 1.日志切面类 //切面类注解配置加两个注解 @Aspect @Component public class LoggerAspect {public Object log(Pr ...

最新文章

  1. 商贸通服装鞋帽版客户端无法连接服务器的问题(自己遇到的,已解决)
  2. 国外发明的10大仿生机械,这才是真正的黑科技!
  3. 【Spring注解系列02】@CompentScan与@CompentScans
  4. JVM参数设置、分析(转)
  5. ubuntu1604安装tensorflow
  6. wordpress 运行_如何为您的教室设置和运行WordPress
  7. Linux学习总结(73)——Linux高频命令大总结
  8. 均匀分布(uniform distribution)期望的最大似然估计(maximum likelihood estimation)
  9. mobaxterm为什么无法连接_为什么 TCP 建立连接需要三次握手
  10. mysql存储过程实现_原来MySQL的存储过程也可以这么玩?
  11. C语言自学完备手册(02)——变量的声明与定义
  12. matlab 太阳角,matlab – 来自太阳位置和观察者位置的时间
  13. Ajax关于readyState和status
  14. jdk eclipes 配置 MySql navicat8_mysql_en安装
  15. PDF在线转Word文本软件
  16. 读书感受 之 《学会提问》
  17. java的“看门狗”锁续期可以用php redis这样实现【php锁续期、分布式锁、无锁请求队列超卖】解决【商家超卖(商品库存控制)、用户超买(秒杀订单控制)】问题。非demo 线上一直在用
  18. c语言char a 4,char a:4;是什么意思C++
  19. Nett源码剖析注册通道2021SC@SDUSC
  20. roadflow 企业微信 工作流程引擎的配置与使用

热门文章

  1. centos中文、英文乱码
  2. python里的非_python中或与非
  3. 追光的人 团队团队展示
  4. 服务器winsxs文件夹怎么清理工具,如何清理Win7系统winsxs文件夹中的垃圾?
  5. FME不需要符号库转换CAD填充
  6. 逍遥叹歌词--《仙剑奇侠传》
  7. 15天深度复习JavaWeb的详细笔记(七)——Request、Response
  8. 21个奇葩注释,程序员看了都点赞
  9. FFmpeg —— 14.示例程序(八):音频编码器(PCM编码为AAC)
  10. Python中Print()函数的用法___实例详解(全,例多)