zoukankan      html  css  js  c++  java
  • Spring_Aop的xml和注解的使用

    动态代理:

        目的:在不改变源代码的情况下,对方法进行增强!
        
        动态代理又分为两种:
        1.第一个就是基于接口的动态代理,他是由jdk提供的
        2.基于子类的动态代理:cglib提供的:要想使用基于子类的动态代理:就必须得导入cglib的jar包
        
        特性:被代理对象的任意方法
        

    Spring_aop:总结
    aop(Aspect Oriented Programming) :面向切面编程

    切面:相对于业务主线的额外的功能模块
    在不改变程序源代码的情况下对方法进行增强

    aop的底层原理就是动态代理
        aop的底层他会自动的根据代码,选择是使用基于还是使用子类的动态代理!
        
        使用aop进行编程有啥好处呢?
            1.简化业务代码
            2.维护简单
            
            Aop相关术语
            Joinpoint(连接点):执行的方法
            pointcut(切入点):被增强的方法
            Advice(通知/增强):就是额外的功能模块
                前置通知
                后置通知
                异常通知
                最终通知
                环绕通知
                Aspect(切面):
                    对那个方法进行怎样的增强
            学习Aop重点关注的事情是啥呢?
            1.重点关注的是一个一个的额外的功能模块
            2.aop的配置
    第三 spring Aop的开发流程
                定义一个切面类
                普通的Java类,在这个类中通过一个一个的方法对目标对象进行增强
                
                2.配置Aop
                    在xml里面配置文件中aop
                    i.将切面类交给spring管理
                    
                    ii.声明Aop配置
                    <aop:config>
                    iii.定义切入点
                    aop:pointcut
                    iiii.定义通知类型
                    <aop:aspect ref = "切面类的引用">
                        前置通知
                        <aop:before method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                        后置通知<aop:afterRunturning method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                        异常通知<aop:after-throwing method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                        最终通知<aop:after method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                        注意:异常通知只有出现了异常了 才会有通知
                    </aop:aspect>
                    基于注解的Aop配置(结合xml)
                1.将切面类交给spring管理
                2.使用注解的形式代替xml中的aop的配置
                3.使用注解配置spring的ioc或者aop的时候都需要开启对注解的支持!
                
                注意:使用注解配置Aop和xml配置Aop在后置通知的时候,有一些差别!
                注解的配置:是最后执行后置通知!
                
                纯注解配置Aop
                1.声明配置类
                2.开启对ioc的支持
                3.开启对aop注解的支持
                @EnableAspectJAutoProxy
                
    开发步骤以及代码的解释
            <!-- 将切面类交给spring管理 -->
            <bean id="logger" class="cn.itcast.utils.Logger"></bean>
            
            <!-- 声明AOP配置:需要使用aop的命名空间(必须导入aop的约束)
            aop:config : 声明aop配置
         -->
        <aop:config>
        
        <!-- 定义切入点:定义被增强的方法
                expression : execution(类的修饰符 返回值 包名.包名...类名.方法名(参数列表))
                1.类的修饰符可以省略 :返回值 包名.包名...类名.方法名(参数列表)
                2.返回值可以使用*号代替:标识任意返回值都可以
                3.包名可以使用*号代替,一个包需要一个*
                4.包名..代表此包   以及   此包的任意子包
                5.类名可以使用*代替,代表任意类
                6.方法名可以使用*代理,代表任意方法
                7.参数类别可以使用..代表任意参数
                
                **** 此写法 * *..*.*(..) 不推荐
                
             -->
            <aop:pointcut expression="execution(* cn.itcast.service.impl..*.*(..))" id="pt"/>
            
            
            
            <!-- 配置切面
                    aop:aspect
                        ref:被spring管理的切面类的引用
            -->
            <aop:aspect ref="logger">
            
            
                <!-- 定义通知的类型
                    aop:before  定义前置通知
                        method:切面类中定义的方法名
                        pointcut-ref:切入点表达式是引用
                -->
                <aop:before method="before" pointcut-ref="pt"/>
                
                这是xml里面的配置
                
    注解配合xml使用代码以及解释
        <!-- 开启对spring ioc的支持 -->
        <context:component-scan base-package="cn.itcast"></context:component-scan>
        
        <!-- 开启对aop注解的支持 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
        
        
        /*
     * 切面类:
     *         对目标对象进行日志部分的增强是通过此类中的方法来实现
     * 在切面类上
     *         定义切面类
     * 在切面方法上
     *         使用注解的形式定义通知类型
     */
    @Component("logger")
    @Aspect
    public class Logger {//这是配置到类上的

    /**
         * 抽取切入点表达式
         *         @Pointcut:定义切入点表达式
         *             这个注解需要配置到方法上,这个方法是一个空的方法
         *             应用这个切入点表达式的时候,只需要引入方法名就可以了
         *             但是需要  方法名()   需要加括号
         */
        @Pointcut(value="execution(* cn.itcast.service.impl..*.*(..))")//注意:类名前面那两个点改成一个点也是可以的
        @Pointcut(value="execution(* cn.itcast.service.impl.*.add*(..))")//这是指定对那个方法进行增强
        public void pt() {//定义一个通用的,这样前置通知,后置通知等等用的时候只需要引用这个方法名就行了
            
        }
        
        /**
         * 定义前置通知
         *     @Before :
         *         value : 可以是一个切入点表达式,也可以是一个切入点表达式的引用
         *             切入点表达式    
         */
        @Before("pt()")
        public void before() {
            System.out.println("进入方法之前打印日志");
        }
        
                
        *这是注解配置xml的方法

    纯注解的配置方式


    /*
     * 切面类:
     *         对目标对象进行日志部分的增强是通过此类中的方法来实现
     * 在切面类上
     *         定义切面类
     * 在切面方法上
     *         使用注解的形式定义通知类型
     */
    @Component("logger")
    @Aspect
    public class Logger {
        
        /**
         * 抽取切入点表达式
         *         @Pointcut:定义切入点表达式
         *             这个注解需要配置到方法上,这个方法是一个空的方法
         *             应用这个切入点表达式的时候,只需要引入方法名就可以了
         *             但是需要  方法名()   需要加括号
         */
        @Pointcut(value="execution(* cn.itcast.service.impl..*.*(..))")
        public void pt() {
            
        }
        
        /**
         * 定义前置通知
         *     @Before :
         *         value : 可以是一个切入点表达式,也可以是一个切入点表达式的引用
         *             切入点表达式    
         */
        @Before("pt()")
        public void before() {
            System.out.println("进入方法之前打印日志");
        }
        
        
        @AfterReturning("pt()")
        public void afterReturning() {
            System.out.println("执行目标方法得到返回值后打印日志");
        }
        
        @AfterThrowing("pt()")
        public void afterThrowing() {
            System.out.println("抛出异常打印日志");
        }
        
        @After("pt()")
        public void after() {
            System.out.println("在最终代码块中打印日志");
        }
        
        //5.定义环绕通知
        /**
         * 环绕通知是spring提供的一种
         *     让程序员手动指定要执行的增强方法的一种手段,
         * 在此方法中可以根据需求自定义以上4中通知类型
         *     在环绕通知中,需要手动去调用被增强的方法
         *     借助spring提供的一个对象ProceedingJoinPoint
         *             此对象中有一个方法,可以调用被增强的方法
         *         pjp.proceed();执行被增强的的方法
         *             eg:动态代理中的,method.invoke();
         *
         * @throws Throwable
         */
        @Around("execution(* cn.itcast.service.impl..*.*(..))")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("前置通知");
            Object obj = null;
            try{
                obj = pjp.proceed();
                System.out.println("后置通知");
            }catch(Exception e){
                System.out.println("异常通知");
                e.printStackTrace();
            }finally{
                System.out.println("最终通知");
            }
            return obj;
        }
    }







    /spring的配置类
    //在配置类中替换xml配置文件中的剩余配置项

    /**
     * 1。声明配置类
     * 2。开启对ioc的支持
     * 3。开启对AOP注解的支持
     *         @EnableAspectJAutoProxy
     *
     */
    @Configuration
    @ComponentScan(basePackages="cn.itcast")
    @EnableAspectJAutoProxy
    public class Config {

    }





        public class Client {

        public static void main(String[] args) {
            //测试ioc的配置
            //ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
            ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
            
            CustomerService customerService = (CustomerService)ac.getBean("customerService");
            customerService.updateCustomer();
        }
    }
            这是纯注解的方式
            
            Aop事物案例
            
            @Component("logger")
    @Aspect
    public class Logger {
        
        @Pointcut(value="execution(* cn.crm.service.impl..*.*(..))")
        public void pt(){
            
        }
        
        @Around(value="pt()")
        public Object tx(ProceedingJoinPoint pjp) throws Throwable{
            Session session = null;
            Transaction tx = null;
            
            Object obj = null;
            
            try {
                session = HibernateUtils.getCurrentSession();
                tx = session.beginTransaction();
                
                obj = pjp.proceed();
                
                tx.commit();
                
            } catch (Exception e) {
                System.out.println("出现异常了");
                tx.rollback();
                
            }finally {
                
                System.out.println("最终执行的代码");
                
            }
            
            return obj;
            
        }
        

    }


        public class Client{
            public static void main(String[] args) {
            
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
            
            CustomerService customerService = (CustomerService)ac.getBean("customerService");
            
            
            Customer customer = new Customer();
            
            customer.setCustName("hello");
            
            customerService.addCustomer(customer);
        }
            
        }

            xml配置:
             <context:component-scan base-package="cn.crm"></context:component-scan>
            
            <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
            
            
            
            这是一个小小的Aop的事物案例,
    当然Spring也提供了事物的支持,但是今天只做了个Aop的事物,希望对大家有帮助

  • 相关阅读:
    java中栈内存和堆内存的简单理解
    java中构造函数与一般函数的区别

    另一部漫画
    海边的卡夫卡
    11-12
    这篇大概值一百万吧
    我的千岁寒
    11-9
    嗯……………股票已经涨的我不想上班了
  • 原文地址:https://www.cnblogs.com/guanzhuang/p/7684690.html
Copyright © 2011-2022 走看看