spring Aop解释以及使用

 

  • 自我理解
    • 在方法体中切一刀,插入想要执行的代码(插入的代码不是固定的)
  • 概念
    • 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
      • 自我理解:方法名
    • 目标(Target):被通知(被代理)的对象
      • 自我理解:那个方法就是目标
    • 通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)
      • 自我理解:在你的方法体加入代码,让你这个方法体帮我运行
    • 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),请注意:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
      • 自我理解:砍一刀,插入代码都是对代理对象
    • 切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。 (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)
      • 自我理解:从哪开始切
    • 适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)
      • 自我理解:找到合适的类或者方法插入代码
    • 工具类org.springframework.aop.framework.ProxyFactoryBean用来创建一个代理对象,在一般情况下它需要注入以下三个属性:
      • proxyInterfaces:代理应该实现的接口列表(List)
      • interceptorNames:需要应用到目标对象上的通知Bean的名字。(List)
      • target:目标对象 (Object)
    • 前置通知(org.springframework.aop.MethodBeforeAdvice):在连接点之前执行的通知()
      • 在你的方法体之前运行
    • 后置通知(org.springframework.aop.AfterReturningAdvice):在连接点正常完成后执行的通知
      • 在你的方法体后面运行
    • 环绕通知(org.aopalliance.intercept.MethodInterceptor):包围一个连接点的通知,最大特点是可以修改返回值,由于它在方法前后都加入了自己的逻辑代码,因此功能异常强大。 它通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用,这样目标方法就不会执行)
      • 在你的方法体前后都运行,(但独看概念,感觉就是前置通知加上后置通知,那可就错了),前后通知,前置通知有三个参数,后置通知有四个参数,而环绕通知只有一个参数就是目标对象,他们是不能嵌套使用的,就比如环绕嵌套里面前置对象,具体看代码
    • 适配器(org.springframework.aop.support.RegexpMethodPointcutAdvisor) 适配器=通知(Advice)+切入点(Pointcut)
  • IBookService接口类
    • 里面定义的抽象方法的方法
      • 购书方法,谁买的书,买的什么书,书的价格
      • public boolean buy(String userName,String bookName,Double price);
      • 发表书评论,谁发布的,发布的什么内容
      • public void comment(String userName,String comments);
  • BookServiceImpl实现接口中的方法
    • public BookServiecImpl(){
      • super();
    • }
    • 购书的(通过控制台的输出方式模拟购书)
      • public boolean buy (String userName,String bookName,Double price){
        • if(null==price||price<=0){
          • throw new MyThrowsAdice("book price exception");需要try catch(这个是异常通知)
        • }
      • System.out.println(userName + " buy " + bookName + ", spend " + price);
      • retuen true;返回值
      • }
    • 发布内容的(通过控制台的输出方式模拟发表书评)
      • public void comment(String userName, String comments){
        • System.out.println(userName + " say:" + comments);
      • }
  • Spring.xml中的相关配置(如果取的名字是其他,需要到核心配置文件中注册(spring.xml))
    • <!-- 声明目标 class为绝对路径 -->
      • <bean id="bookServie" class="P2.BookServiceImpl"></bean>
    • <!-- 前置通知 -->
      • <bean id="beforeAdvice" class="P2.MyMethodBeforeAdvice"></bean>
        • MyMethodBeforeAdvice类中实现(org.springframework.aop.MethodBeforeAdvice;)
          • 重写的方法
            • before(Method arg0 ,Object[] arg1,Object arg2){
              • //拿到目标的方法名
              • String name=arg0.getName(); //所以第一个参数是目标方法名
              • System.out.println("前置通知"+"方法名"+name+",参数"+Arrays.toString(arg1)+",类名"+arg2.getClass().getName());
            • }
    • <!--后置通知 -->
      • <bean id="afterAdvice" class="P2.MyAfterReturningAdvice"></bean>
        • MyAfterReturningAdvice类中实现(org.springframework.aop.AfterReturningAdvice;)
          • 重写的方法
            • afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3){
              • System.out.println("后置对象:返回值"+arg0+",方法名"+arg1.getName()+"对象数组"+Arrays.toString(arg2)+",目标类名"+arg3.getClass());
            • }
    • <!-- 环绕通知 -->
      • <bean id="methodInterceptor" class="P2.MyMethodInterceptor"></bean>
        • MyMethodInterceptor类中实现(import org.aopalliance.intercept.MethodInterceptor;)
          • 重写的方法
            • invoke(MethodInvocation arg0){
              • System.out.println("环绕通知1");
              • //目标对象
              • Object obj = arg0.getThis();
              • //得到目标方法的参数
              • Object[] args = arg0.getArguments();
              • //得到目标方法,运行目标方法
              • Object invoke = arg0.getMethod().invoke(obj, args);
              • System.out.println("环绕通知2");
              • return invoke;
            • }
    • <!--工具类(一定要写,这个是把这个东西关联起来的)-->
      • <bean id="proxyBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        • <!--代理的 目标赋值 -->
        • <property name="target">
          • <!--通过反射会实现这个类 -->
          • <ref bean="bookServie" /> (这里是写的目标类的id)
        • </property>
        • <!-- 代理的通知赋值 -->
        • <property name="interceptorNames">
          • <list>
            • <!--想显示什么通知写什么 -->
            • <value>pointCutAdvice</value>
            • <value>afterAdvice</value>
            • <value>methodInterceptor</value>
          • </list>
        • </property>
        • <!-- 代理需要实现的接口 -->
        • <property name="proxyInterfaces">
          • <list>
            • <!-- 实现的接口 -->
            • <value>P2.IBookService</value>(这是那个接口类)
          • </list>
        • </property>
      • </bean>
    • <!-- 适配器 (如果没写这个这些通知只能指定类,类中所以的方法都具有,写了这个可以匹配指定方法)-->
      • <bean id="pointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        • <property name="advice">
          • <ref bean="beforeAdvice"/>(前置通知的id)
        • </property>
        • <!-- 正则表达式 -->
        • <property name="pattern">
          • <value>.*buy</value>
        • </property>
      • </bean>
  • MyThrowsAdvice中继承 Exception 实现 ThrowsAdvice (org.springframework.aop.ThrowsAdvice)
  • 最终的测试结果(按以上代码来写,这两个方法运行的结果是Buy有前置通知,Comment没有前置通知)
    • Buy方法
      •  
        • 把这个异常通知注释掉了运行的结果
        • 当没有注释,会打印这个异常
    • 运行Comment
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值