zoukankan      html  css  js  c++  java
  • Spring之注解实现aop(面向切面编程)

    1:Aop(aspect object programming)面向切面编程,名词解释:
        1.1:功能:让关注点代码与业务逻辑代码分离
        1.2:关注点
            重复代码就叫做关注点
        1.3:切面
            关注点形成的类,就叫做切面(类)
            面向切面编程,就是指对很多功能都有的重复代码抽取,再在运行的时候往业务方法上动态植入"切面类代码";
        1.4:切入点
            执行目标对象方法,动态植入切面代码
            可以通过切入点表达式,指定拦截那些类的那些方法,给指定的类在运行的时候植入切面类代码;
    2:注解方式实现aop编程
        2.1:开发步骤
            (1):先引入aop相关的jar文件
                spring-aop-3.2.5.RELEASE.jar【去spring3.2源码里面找】
                aopalliance.jar【去spring2.5源码/lib/aopalliance文件里面找】
                aspectjweaver.jar【去spring2.5源码/lib/aspectj文件里面找】或者【aspectj-1.8.2/lib/aspectjweaver.jar】
                aspectjrt.jar【去spring2.5源码/lib/aspectj文件里面找】或者【aspectj-1.8.2/lib/aspectjrt.jar】

            《注意:用到的spring2.5版本的jar本舰,如果用jd1.7版本可能会出现问题,
                  需要升级以下aspectj组件,即使用aspectj-1.8.2版本中提供的jar文件aspectjweaver.jar和aspectjrt.jar》   

            (2)bean.xml中引入aop名称空间
          技巧:找到文件spring-framework-3.2.5.RELEASE/docs/spring-framework-reference/htmlsingle
             打开index.html搜索xmlns:aop然后找到下面红色三句话,分别拷贝到bean.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"

              xsi:schemaLocation="http://www.springframework.org/schema/beans

                http://www.springframework.org/schema/beans/spring-beans.xsd

              http://www.springframework.org/schema/aop

              http://www.springframework.org/schema/aop/spring-aop.xsd">

          拷贝之后的bean.xml如下所示:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:p="http://www.springframework.org/schema/p"
     5     xmlns:context="http://www.springframework.org/schema/context"
     6     xmlns:aop="http://www.springframework.org/schema/aop"
     7     xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/context
    11         http://www.springframework.org/schema/context/spring-context.xsd
    12         http://www.springframework.org/schema/aop
    13         http://www.springframework.org/schema/aop/spring-aop.xsd">
    14 
    15 </beans> 

        (3):bean.xml中开启aop注解扫描,如下配置所示:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:p="http://www.springframework.org/schema/p"
     5     xmlns:context="http://www.springframework.org/schema/context"
     6     xmlns:aop="http://www.springframework.org/schema/aop"
     7     xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans
     9         http://www.springframework.org/schema/beans/spring-beans.xsd
    10         http://www.springframework.org/schema/context
    11         http://www.springframework.org/schema/context/spring-context.xsd
    12         http://www.springframework.org/schema/aop
    13         http://www.springframework.org/schema/aop/spring-aop.xsd">
    14 
    15       <!-- 开启注解扫描 -->
    16       <context:component-scan base-package="com.bie.aop"></context:component-scan>   
    17         
    18       <!-- 开启aop注解方式,默认为false -->    
    19       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    20       
    21 </beans>        

         (4):开始写一个切面类,源码如下所示:

     1 package com.bie.aop;
     2 
     3 import org.aspectj.lang.annotation.After;
     4 import org.aspectj.lang.annotation.Aspect;
     5 import org.aspectj.lang.annotation.Before;
     6 import org.aspectj.lang.annotation.Pointcut;
     7 import org.springframework.stereotype.Component;
     8 
     9 
    10 /** 
    11 * @author BieHongLi 
    12 * @version 创建时间:2017年3月28日 下午9:10:43 
    13 * @Aspect:指定当前类为切面类
    14 */
    15 @Component  //加入到IoC容器
    16 @Aspect  //指定当前类为切面类
    17 public class Aop {
    18 
    19     //指定切入点表达式,拦截那些方法,即为那些类生成代理对象
    20     //@Pointcut("execution(* com.bie.aop.UserDao.save(..))")  ..代表所有参数
    21     //@Pointcut("execution(* com.bie.aop.UserDao.*())")  指定所有的方法
    22     //@Pointcut("execution(* com.bie.aop.UserDao.save())") 指定save方法
    23     
    24     @Pointcut("execution(* com.bie.aop.UserDao.*(..))")
    25     public void pointCut(){
    26         
    27     }
    28     
    29     @Before("pointCut()")
    30     public void begin(){
    31         System.out.println("开启事务");
    32     }
    33     
    34     @After("pointCut()")
    35     public void close(){
    36         System.out.println("关闭事务");
    37     }
    38     
    39 }

        (5):写好切面类就可以写执行目标对象方法,接口和实现类如下所示:

     1 package com.bie.aop;
     2 
     3 /** 
     4 * @author BieHongLi 
     5 * @version 创建时间:2017年3月28日 下午9:09:29 
     6 * 
     7 */
     8 
     9 public interface IUserDao {
    10 
    11     public void save();
    12 }
     1 package com.bie.aop;
     2 
     3 
     4 import org.springframework.stereotype.Component;
     5 
     6 /** 
     7 * @author BieHongLi 
     8 * @version 创建时间:2017年3月28日 下午9:09:53 
     9 * 目标对象
    10 */
    11 @Component
    12 public class UserDao implements IUserDao{
    13     
    14     @Override
    15     public void save() {
    16         System.out.println("..核心业务--核心业务..");
    17     }
    18 
    19     
    20 }

        (6):最后就可以进行进行测试了,源码如下所示:

     1 package com.bie.aop;
     2 
     3 import org.junit.Test;
     4 import org.springframework.context.ApplicationContext;
     5 import org.springframework.context.support.ClassPathXmlApplicationContext;
     6 
     7 /** 
     8 * @author BieHongLi 
     9 * @version 创建时间:2017年3月28日 下午9:13:18 
    10 * 
    11 */
    12 public class AopTest {
    13 
    14     ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    15     
    16     //目标对象有实现接口,spring会自动选择"jdk代理【动态代理】"
    17     //动态代理的标识:class com.sun.proxy.$Proxy10
    18     @Test
    19     public void test01(){
    20         IUserDao dao =  (IUserDao) ac.getBean("userDao");
    21         System.out.println(dao.getClass());
    22         dao.save();
    23     }
    24     
    25     
    26     //class com.bie.aop.OrderDao$$EnhancerByCGLIB$$4952a60a
    27     //目标对象没有实现接口,spring会用"cglib代理哦"
    28     @Test
    29     public void testCglib(){
    30         OrderDao dao =  (OrderDao) ac.getBean("orderDao");
    31         System.out.println(dao.getClass());
    32         dao.save();
    33     }
    34 }

      3:心得体会和报错解决:

        3.1:虽然案例很简单很简单,但是我花了三四个小时,为什么呢!我用junit测试spring写的注解实现aop(面向切面编程)。

        3.2:编辑环境:eclipse+tomcat8.0+jdk1.8,为什么说编辑环境呢,因为jdk1.8和spring好像有仇似的,开始我安装的jdk是1.8版本的,总之包很多很多错,主要的caused by:java.lang.IllegalArgumentException【看错误主要看caused by】

        3.3:这个错是UserDao dao =  (UserDao) ac.getBean("userDao");---》

            IUserDao dao =  (IUserDao) ac.getBean("userDao");

            意思就是说必须使用接口来接受从IoC容器获取的,不能使用实现类接受,不然报的错够你喝一壶了

    java.lang.ClassCastException: com.sun.proxy.$Proxy10 cannot be cast to com.bie.aop.UserDao
        at com.bie.aop.AopTest.test01(AopTest.java:18)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

         3.4:然后呢,我就思考就要换成jdk1.7,我去oracle官网搜了,已经没了jdk1.7,我又去我的百度云翻出1.7,然后安装,之后呢,我就验证呗,其实安装之前我也思考过,能不能安装1.8之后再安装1.7,安装肯定没毛病啊,但是总要配置环境变量吧,我就配置jdk1.7之后发现验证的时候还是显示是jdk1.8,我就赶紧思考啊,思考过后我考虑应该把jdk1.7,jdk1.8都卸载了,然后我都卸载了,然后重新安装jdK1.7,之后配置之后,其实主要给Java_home环境变量改一下就行,然后验证就显示jdk1.7版本了,之后呢又去测试程序,然而呢,程序之前是jdk1.8,全部报错了,我又把jdk1.8换成1.7;详细更换jdk1.8--->jdk1.7的过程如下所示;


    首先,第一步:点击window-->Preferences-->Java-->Installed JREs-->ADD

    第二步:点击add之后显示如下所示

    第三步:点击next之后点击如下图所示的Directory即可;



    第四步:点击项目右击

    第五步:如下所示

    第六步:如下所示

    第七步:如下所示

    第八步:如下所示

    第九步:如下所示

    然后呢,jdk总算是由jdk1.8换成了1.7,这个过程虽然比较麻烦,但是解决问题,我也很开心啊,加油吧,骚年~~~

  • 相关阅读:
    标准输出stdout、标准错误stderr 分类: python python基础学习 2013-06-17 18:08 308人阅读 评论(0) 收藏
    python数据持久存储:pickle模块的基本使用 分类: python python基础学习 python 小练习 2013-06-17 14:41 209人阅读 评论(0) 收藏
    解析XML文件总结 分类: python基础学习 python 2013-06-17 12:04 232人阅读 评论(0) 收藏
    使用set()求出列表交集 分类: python基础学习 2013-06-16 17:00 241人阅读 评论(0) 收藏
    [搜索][51nod] 1268 和为K的组合
    [51nod] 1279 扔盘子
    [记忆化搜索] [洛谷] P1464 Function
    [贪心][51nod] 1133 不重叠的线段
    [二分] [51nod]1010 只包含因子2 3 5的数 lower_boud
    万年历查询 c++ 黑窗
  • 原文地址:https://www.cnblogs.com/biehongli/p/6640406.html
Copyright © 2011-2022 走看看