zoukankan      html  css  js  c++  java
  • 006-搭建框架-实现AOP机制【三】AOP技术

    2.3、spring+aspectj

      Spring在集成了aspectj后,同时也保留了以上的切面与代理的配置方式。

      将Spring与aspectj集成与直接使用aspectj不同,不需要定义Aspectj类(它扩展了Java语法的一种新语言,还需要特定的编译器),只需要使用Aspectj切点表达式即可。

    1、Spring + Aspectj(基于注解:通过Aspectj execution表达式拦截方法)

    增加GreetingAspect类

    View Code

      其中包含了环绕增强

      该类中的@Aspect注解,表明该类是一个Aspect,其实就是Advisor。该类无需实现任何的接口,只需定义一个方法(名称无所谓),在方法上标注Around注解即可,在注解中使用Aspectj切点表达式。方法的参数中包含一个ProceedingJoinPoint对象,他在aop中称为joinpoint(连接点),可以通过该对象获取方法的任何信息。

      切点表达式分析,execution(* com.lhx.chapter4.aop.GreetingImpl.*(..))

      execution()标示拦截方法,括号中需要定义匹配的规则

      第一个“*”表示方法的返回值是任意的

      第二个“*”表示匹配该类中的所有方法

      (..)表示方法的参数是任意的

    配置Spring的xml

    View Code

      proxy-target-class,默认是false,只能代理接口,默认使用JDK代理,true时,代理目标类,使用CGLib代理。

    client调用

    View Code

    2、Spring + Aspectj(基于注解:通过Aspectj @annotation 表达式拦截方法)

    为拦截指定的注解的方法,需要先自定义一个注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Tag {
    }

      以上定义了一个注解,此注解可标注在方法上,在运行时生效。

    Greeting的Aspect类

    View Code

      使用了@annotation()表达式,只需要在括号内定义需要拦截的注解名称即可。

      直接将Tag注解定义在想要拦截的方法上即可。  

    View Code

    client调试

    View Code

    当然也需要使用上一个的xml文件

    相关注解说明

      Before--前置增强

      After--后置增强

      Aroung--环绕增强

      AfterThrowing--抛出增强

      DeclareParents--引入增强

      AfterReturning--返回后增强,即finall增强,相当于finally语句,方法结束后执行,比After还要晚一些。

    3、Spring + Aspectj:引入增强

    定义一个引入增强类

    package com.lhx.chapter4.aop.aopaspectjdeclare;
    
    import com.lhx.chapter4.aop.springaopintroductionadvice.Apology;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class GreetingAspectDeclare {
        @DeclareParents(value = "com.lhx.chapter4.aop.GreetingImpl",defaultImpl = ApologyImpl.class)
        private Apology apology;
    }
    View Code

      在Aspect类中定义一个需要引用增强的接口,它也就是运行时需要动态实现的接口,在这个接口上标注@DeclareParents注解,注解属性有,

        value--目标类,defaultImpl--引入接口的默认实现类。

    对引入接口提供实现

    package com.lhx.chapter4.aop.aopaspectjdeclare;
    
    import com.lhx.chapter4.aop.springaopintroductionadvice.Apology;
    
    public class ApologyImpl implements Apology {
        @Override
        public void saySorry(String name) {
            System.out.println("Sorry " + name);
        }
    }
    View Code

    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:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--扫描指定包(将带有Compontent注解的类自动定义为Spring bean)-->
        <context:component-scan base-package="com.lhx.chapter4.aop"></context:component-scan>
        <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
    </beans>
    View Code

    客户端校验

    package com.lhx.chapter4.aop.aopaspectjdeclare;
    
    import com.lhx.chapter4.aop.Greeting;
    import com.lhx.chapter4.aop.springaopintroductionadvice.Apology;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Client {
        public static void main(String[] args) {
            //获取spring content
            ApplicationContext context =new ClassPathXmlApplicationContext("application-aop-declare.xml");
            //从Content中根据id获取Bean对象,其实就是一个代理
            Greeting greetingProxy = (Greeting) context.getBean("greetingImpl");
            greetingProxy.sayHelloNoPreSub("muzixu ");
            Apology apology = (Apology) greetingProxy;
            //将目标类强制向上转型为Apology接口类型【引入增强的特性,即“动态接口实现”功能】
            apology.saySorry("Jack");
    
        }
    }
    View Code

    4、Spring + Aspectj:基于配置

      除了使用aspectj注解来定义切面外,Spring AOP也提供了基于配置的方式来定义切面类

    配置

    <?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:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
        <bean id="greetingImpl" class="com.lhx.chapter4.aop.GreetingImpl"></bean>
        <bean id="greetingAspect" class="com.lhx.chapter4.aop.aopaspectj.GreetingAspect"></bean>
        <aop:config>
            <aop:aspect ref="greetingAspect">
                <aop:around method="around" pointcut="execution(* com.lhx.chapter4.aop.GreetingImpl.*(..))"/>
            </aop:aspect>
        </aop:config>
    </beans>
    View Code

    client使用  

    package com.lhx.chapter4.aop.aopaspectjconfig;
    
    import com.lhx.chapter4.aop.Greeting;
    import com.lhx.chapter4.aop.springaopintroductionadvice.Apology;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Client {
        public static void main(String[] args) {
            //获取spring content
            ApplicationContext context =new ClassPathXmlApplicationContext("application-aop-config.xml");
            //从Content中根据id获取Bean对象,其实就是一个代理
            Greeting greetingProxy = (Greeting) context.getBean("greetingImpl");
            greetingProxy.sayHelloNoPreSub("muzixu ");
    
        }
    }
    View Code

    三、aop总结

    1、思维导图

      

    2、各类增强类型对应的解决方案

    3、spring aop的URL类图框架

  • 相关阅读:
    ImportError: No module named MySQLdb 解决方案
    Python在函数中使用*和**接收元组和列表
    ADB故障时的一些命令
    WebBrowser网页操作之提取获取元素和标签(完整篇)
    单台服务器并发百万级配置(转)
    高并发高负载的大型网站系统架构(转)
    系统架构师的九种能力
    一个操作oracle的c#类 含分页
    我们应该如何做需求分析(转)
    怎样查看oracle当前的连接数
  • 原文地址:https://www.cnblogs.com/bjlhx/p/7732827.html
Copyright © 2011-2022 走看看