zoukankan      html  css  js  c++  java
  • spring的aop 基于schema

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程

    一 前期工作

    1.新建一个java项目,我是使用的maven,所以我新建了一个简单的maven项目,因为maven项目可以省去到处找jar包的时间,还是比较方便的

    2.引入需要的jar包,我的pom文件中的dependency为

    <dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.12</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-core</artifactId>
    			<version>3.2.16.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-expression</artifactId>
    			<version>3.1.4.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context</artifactId>
    			<version>3.2.16.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-beans</artifactId>
    			<version>3.2.16.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</artifactId>
    			<version>3.2.11.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aspects</artifactId>
    			<version>3.2.1.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjweaver</artifactId>
    			<version>1.7.1</version>
    		</dependency>
    
    
    
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-asm</artifactId>
    			<version>3.1.4.RELEASE</version>
    		</dependency>
    
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>1.2.15</version>
    			<exclusions>
    				<exclusion>
    					<groupId>com.sun.jmx</groupId>
    					<artifactId>jmxri</artifactId>
    				</exclusion>
    				<exclusion>
    					<groupId>com.sun.jdmk</groupId>
    					<artifactId>jmxtools</artifactId>
    				</exclusion>
    				<exclusion>
    					<groupId>javax.jms</groupId>
    					<artifactId>jms</artifactId>
    				</exclusion>
    			</exclusions>
    		</dependency>
    
    		<dependency>
    			<groupId>commons-logging</groupId>
    			<artifactId>commons-logging</artifactId>
    			<version>1.2</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-collections4</artifactId>
    			<version>4.1</version>
    		</dependency>

    3.新建java文件

    ①接口,新建一个HelloService的接口

    ②实现类,新建一个HelloServiceImpl的类,实现上面的接口

    ③切面,新建一个HelloAspect的类,在aop中就叫做前面

    ④测试类,新建一个AopTest的测试类

    4.在src/java/resource文件夹下面建立一个aopContext.xml的xml文件,schema为

    <?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"  
            xsi:schemaLocation="  
               http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
               http://www.springframework.org/schema/aop  
               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">  

    5.将bean资源引入xml

     <bean id="hello" class="com.qiao.aop.HelloServiceImpl"/>
           <bean id="aspect" class="com.qiao.aop.HelloAspect" />

    二 aop测试开始

    1.前置通知

    HelloService:  public void beforeSay(String param);

    HelloServiceImpl: public void beforeSay(String param) {
    System.out.println(" beforeSay method  param="+param);
    }

    HelloAspect: public void beforeSayAspect(String para){
    System.out.println(" aspect before param = "+para);
    }

    aopTest : @Test 

    public void beforeAspectTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("aopContext.xml");

    HelloService hello = (HelloService) app.getBean("hello",HelloService.class);

    hello.beforeSay("hello");
    }

    在xml文件中配置

        <aop:config>
          <span style="white-space:pre">	</span> 	<aop:pointcut expression="<span style="font-family: Arial, Helvetica, sans-serif;">execution(* com.qiao.aop.*.*(..)) and args(param)</span>" id="pointcut"/>
           <span style="white-space:pre">	</span>	<aop:aspect ref="aspect">
           		<aop:before pointcut-ref="pointcut"  method="beforeSayAspect(java.lang.String)" arg-names="param"/>
           	<span style="white-space:pre">	</span></aop:aspect>
           </aop:config>
    (<aop:pointcut> 是定义切入点表达式,execution是切入点表达式,第一个*表示任意返回类型,第二个* 表示com.qiao.aop下面的所有的类,第三个*表示类下的所有方法,括号中的“..”表示方法中的任意参数

    <aop:aspect> ref指向的是切面,在xml文件中配置的切面的id

    <aop:before> 表示这个是前置通知,pointcut-ref指向的是上面pointcut的id,就是使用其中的表达式,也可以在pointcut中直接赋值,即pointcut="execution(* com.qiao.aop.*.*(..)) and args(param)"  在本身直接定义切入点表达式,注意,pointcut和pointcut-ref只能使用一个,两个都使用就会报错。

    注意:在aop:pointcut中的args的参数名必须和aop:before中的arg-names的中的参数必须一样,这样,调用切入点是的时候,才会将切入点方法里面的参数传入通知方法中。即。




    运行aoptest中的beforeAspectTest,最后输出

    在这里面,HelloAspect就是切面,HelloAspect中的方法beforeSayAspect就是通知,HelloService中的方法beforeSay就是切入点。


    2.后置返回通知

    HelloService:public boolean afterSayReturning();

    HelloServiceImpl : public boolean afterSayReturning() {

    System.out.println("after return");

    return true;
    }

    HelloAspect:public void afterAspectReturning(Object val){
    System.out.println(" after aspect returning val = "+val);
    }

    AopTest : @Test
    public void afterReturningAspectTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("aopContext.xml");

    HelloService hello = (HelloService) app.getBean("hello",HelloService.class);
    hello.afterSayReturning();
    }

    xml

    		<aop:config>
           	<span style="white-space:pre">		</span><aop:pointcut expression="execution(* com.qiao.aop.*.*(..))" id="pointcut"/>
           	<span style="white-space:pre">		</span><aop:aspect ref="aspect">
    			<aop:after-returning pointcut-ref="pointcut" method="afterAspectReturning" arg-names="val" returning="val"/>
          <span style="white-space:pre">		</span> 	</aop:aspect>
          <span style="white-space:pre">		</span>     </aop:config>


    最后输出

    这个我估计实在切入点方法执行之后,将返回值放在后置方法中,然后输出。个人猜测啊。

    3.后置异常通知

    HelloService :  public void afterException();

    HelloServiceImpl :   public void afterException() {
    System.out.println("after excetion");
    throw new RuntimeException();
    }

      HelloAspect :  public void afterExceptionAspect(Exception e){
    System.out.println(" after Exception and e is "+e);
    }

    AopTest : @Test
    public void afterExceptionAspectTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("aopContext.xml");

    HelloService hello = (HelloService) app.getBean("hello",HelloService.class);

    hello.afterException();
    }
    xml : 

    	<aop:config>
    		<aop:pointcut expression="execution(* com.qiao.aop.*.*(..))" id="pointcut"/>
    	<span style="white-space:pre">	</span> <aop:aspect ref="aspect">
    		<aop:after-throwing pointcut-ref="pointcut" method="afterExceptionAspect" arg-names="e" throwing="e"/>
    		</aop:aspect>
    	   </aop:config>
    
    结果: 


    (这个应该是吧通知放到了catch里面

    4.后置最终通知:在切入点选择的方法返回时执行,不管是正常返回还是抛出异常都执行

    HelloService : public void afterFinally();

    HelloServiceImpl : public void afterFinally() {
    System.out.println("after finally ");
    throw new RuntimeException();
    }

    HelloAspect : public void afterFinallyAspect(){
    System.out.println("after fianlly aspect");
    }

    AopTest  :  @Test
    public void afterFinallyAspectTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("aopContext.xml");

    HelloService hello = (HelloService) app.getBean("hello",HelloService.class);

    hello.afterFinally();
    }

    xml : 

    		<aop:config>
    		       	<aop:pointcut expression="execution(* com.qiao.aop.*.*(..))" id="pointcut"/>
    		       	<aop:aspect ref="aspect">
    					<aop:after pointcut-ref="pointcut" method="afterFinallyAspect" />
    		       	</aop:aspect>
    	       </aop:config>

    (这个难道是放在try catch中的finally里面执行的?)

    5.环绕通知:环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值

    HelloService:   public void sayAround(String param);

    HelloServiceImpl : public void sayAround(String param) {

    System.out.println(" around  "+param);

    }

    HelloAspect : 
    public Object aroundAspect(ProceedingJoinPoint pjp) throws Throwable{
    System.out.println(" around before ");

    Object val = pjp.proceed(new Object[]{"replace"});

    System.out.println(" around after ");

    return val;
    }

    AopTest  :   @Test
    public void aroundAspectTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("aopContext.xml");

    HelloService hello = (HelloService) app.getBean("hello",HelloService.class);

    hello.sayAround("haha");
    }
    xml : 

    		<aop:config>
    		       	<aop:pointcut expression="execution(* com.qiao.aop.*.*(..))" id="pointcut"/>
    		       	<aop:aspect ref="aspect">
    					<aop:around method="aroundAspect" pointcut-ref="pointcut"/>
    		       	</aop:aspect>
    	       </aop:config>
    最后输出:



    以上只是个人观点,不一定,正确。

    最后推荐大神的博客 : http://www.iteye.com/blogs/subjects/spring3?page=2 ,最近在学习大神的博客,可以看看

  • 相关阅读:
    Tomcat安装与配置
    模板方法模式
    观察者模式
    访问者模式
    策略模式
    迭代器模式
    状态模式
    访问者模式
    备忘录模式
    解释器模式
  • 原文地址:https://www.cnblogs.com/Iqiaoxun/p/5350583.html
Copyright © 2011-2022 走看看