spring的AOP编程

基于注解的方式

cfg.xml中

1     <!-- 通过注释的方式来实现AOP所以要扫描包 -->
2     <context:component-scan base-package="spring_aop_helloworld"></context:component-scan>
3     <!-- 要把切面自动生成代理写上 -->
4     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

要在计算器的每个方法的开始和结束时打印日志文件

首先计算器类被配置成bean,然后

Logging.java

 1 package spring_aop_helloworld;
 2
 3 import java.util.Arrays;
 4
 5 import org.aspectj.lang.JoinPoint;
 6 import org.aspectj.lang.ProceedingJoinPoint;
 7 import org.aspectj.lang.annotation.After;
 8 import org.aspectj.lang.annotation.AfterReturning;
 9 import org.aspectj.lang.annotation.AfterThrowing;
10 import org.aspectj.lang.annotation.Around;
11 import org.aspectj.lang.annotation.Aspect;
12 import org.aspectj.lang.annotation.Before;
13 import org.aspectj.lang.annotation.Pointcut;
14 import org.springframework.core.annotation.Order;
15 import org.springframework.stereotype.Component;
16
17 @Order(2)
18 @Aspect
19 @Component
20 public class Logging {
21     //以这种方式实现重用,不用每次都写execution(* spring_aop_helloworld.Calculator.*(int,int))
22     @Pointcut(value="execution(* spring_aop_helloworld.Calculator.*(int,int))")
23     public void getExpression(){}
24
25     /**
26      * 前置通知,在执行* spring_aop_helloworld.Calculator.*(int,int)(使用了AspectJ表达式)前执行此方法
27      *
28      * JoinPoint j传入参数
29      * j.getSignature().getName()获取方法名
30      * j.getArgs()获取参数数组
31      * */
32     @Before(value="getExpression()")
33     public void before(JoinPoint j){
34         System.out.println("Before通知"+j.getSignature().getName()+":"+Arrays.asList(j.getArgs())    );
35     }
36
37     /**
38      * 后置通知,在执行后执行此方法,不管这个方法有没有异常,能不能执行
39      * */
40     @After(value="execution(* spring_aop_helloworld.Calculator.*(int,int))")
41     public void after(JoinPoint j){
42         System.out.println("After通知"+j.getSignature().getName()+":"+Arrays.asList(j.getArgs()));
43     }
44
45     /**
46      * 返回通知,在方法返回结果之后执行
47      * returning="result"通过参数中和其名字相同的参数传入可以得到被代理方法的返回值
48      * */
49     @AfterReturning(value="execution(* spring_aop_helloworld.Calculator.*(int,int))",returning="result")
50     public void afterReturning(JoinPoint j,Object result){
51         System.out.println("AfterReturning通知:"+j.getSignature().getName()+":"+Arrays.asList(j.getArgs())+":"+result);
52     }
53
54     /**
55      * 异常通知,在方法抛出异常之后执行,若没有异常则不执行
56      * throwing="e"通过参数中和其名字相同的参数传入发生的异常。
57      * 也可以只在指定异常抛出后通知
58      * */
59     @AfterThrowing(value="execution(* spring_aop_helloworld.Calculator.*(int,int))",throwing="e")
60     public void afterEhroeing(JoinPoint j,Exception e){
61         System.out.println("AfterThrowing通知:"+j.getSignature().getName()+":"+Arrays.asList(j.getArgs())+":"+e);
62     }
63
64     /**
65      * 环绕通知
66      * */
67     @Around(value="execution(* spring_aop_helloworld.Calculator.*(int,int))")
68     public Object around(ProceedingJoinPoint p){
69         String methodName = p.getSignature().getName();
70         Object o = null;
71
72         try {
73             System.out.println("-->等同前置通知");
74             o = (int) p.proceed();
75             System.out.println("-->等同返回通知");
76         } catch (Throwable e) {
77 //            throw new RuntimeException(e);
78             System.out.println("-->等同异常通知");
79         }
80         System.out.println("-->等同后置通知");
81         return o;
82     }
83 }

验证器类

package spring_aop_helloworld;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * Order(1)代表切面被调用的优先级,数字越小越先调用
 * Aspect 表示这是一个切面
 * Component 表示这是一个组件,IOC容器可以扫描到
 * */
@Order(1)
@Aspect
@Component
public class Validation {

    //spring_aop_helloworld.Logging.getExpression()返回要代理的方法,实现重用
    @Before(value="spring_aop_helloworld.Logging.getExpression()")
    public void before_validation(JoinPoint j){
        System.out.println("0000验证前置"+j.getSignature().getName());
    }

}

基于配置文件的方式

cfg.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-4.0.xsd">

    <bean id="calculatorImpl" class="spring_aop_xml.CalculatorImpl"></bean>
    <bean id="logging" class="spring_aop_xml.Logging"></bean>
    <bean id="validation" class="spring_aop_xml.Validation"></bean>

    <aop:config>
        <aop:pointcut expression="execution(* spring_aop_xml.Calculator.*(int, int))" id="expression"/>
        <aop:aspect ref="logging" order="2">
            <aop:before method="before" pointcut-ref="expression"/>
            <aop:after method="after" pointcut-ref="expression"/>
            <aop:after-returning method="afterReturning" pointcut-ref="expression" returning="result"/>
            <aop:after-throwing method="afterthrowing" pointcut-ref="expression" throwing="e"/>
            <aop:around method="around" pointcut-ref="expression"/>
        </aop:aspect>
        <aop:aspect ref="validation" order="1">
            <aop:before method="before_validation" pointcut-ref="expression"/>
        </aop:aspect>
    </aop:config>

</beans>

验证器类和日志文件类都和基于注解的一样,只不过去掉注解。

传统的代理方法实现面向切面编程

package spring_aop_old;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CalculatorProxy {
    private Calculator c;

    //通过构造器传入被代理的对象
    public CalculatorProxy(Calculator c) {
        this.c = c;
    }
    //获取代理对象
    public Object getInstance(){
        Object proxy = null;

        InvocationHandler handler = new InvocationHandler() {

            /**
             * 当想要运行被代理对象的相关方法时,代理对象通过调用invoke来调用被代理对象的方法
             *
             * Object proxy是getInstance()返回的代理对象
             * Method method被代理对象的方法
             * Object[] args被代理对象的方法中的参数
             * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) {
                Object result = null;

                System.out.println("之前..类似前置");
                try {
                    result = method.invoke(c, args);
                } catch (Exception e) {
                    System.out.println("异常..类似异常");
                }
                System.out.println("之后..类似后置");

                return result;
            }
        };
        proxy = Proxy.newProxyInstance(c.getClass().getClassLoader(), new Class[]{Calculator.class}, handler);

        return proxy;
    }
}
package spring_aop_old;

public class TestAOPHello {

    public static void main(String[] args) {
        Calculator c = (Calculator) new CalculatorProxy(new CalculatorImpl()).getInstance();
        System.out.println(c.add(1, 2));
        System.out.println(c.div(10, 0));
    }

}
时间: 2024-10-07 05:30:00

spring的AOP编程的相关文章

spring相关—AOP编程简介

1 AOP概述 ●AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是对传统 OOP(Object-Oriented Programming,面向对象编程)的补充. 作用:本质上来说是一种简化代码的方式     继承机制     封装方法     动态代理     -- ●AOP编程操作的主要对象是切面(aspect),而切面模块化横切关注点. ●在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能应用在哪里,以什么方式应用,并且不必

spring之aop编程——基于注解、xml配置文件方式

AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充.spring中AOP的配置方式有2种方式:xml配置和AspectJ注解方式. 一.xml配置的方式: 1.service接口和服务类: package cn.edu.nuc.SpringTest.service; public interface DemoService { public String sayHello(String name) ; } packa

spring相关—AOP编程—数学计算器情景示例讲解(包含注解配置AOP与XML配置AOP)

1.数学计算器 ①数学计算器接口[MathCalculator]            public void add(int i,int j);     public int sub(int i,int j);     public int multi(int i,int j);     public void divide(int i,int j);    ②提供简单实现:加减乘除运算[EasyImpl]    ③在简单实现的基础上让每一个计算方法都能够打印日志[LoginImpl]    

spring相关—AOP编程—切入点、连接点

1 切入点表达式 1.1 作用 通过表达式的方式定位一个或多个具体的连接点. 1.2 语法细节 ①切入点表达式的语法格式 execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表])) ②举例说明 表达式 execution(* com.atguigu.spring.ArithmeticCalculator.*(..)) 含义 ArithmeticCalculator接口中声明的所有方法. com.atguigu.spring.ArithmeticCalc

spring使用aop需要的jar包,和常见异常

3.0以后spring不再一起发布aop依赖包,需要自己导入: 必须包: 这几个jar包分别为 1.org.springframework.aop-3.1.1.RELEASE  这个是spring的 AOP编程必备包 2.cglib-nodep-2.1_3 3.aspectjweaver-1.6.2 4.aspectj-1.6.12 5.aopalliance-1.0 我已打包:下载地址 常见异常: Caused by: java.lang.IllegalArgumentException: e

【Spring】AOP之JDK动态代理和CGLib动态代理

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.JAVA动态代理  1.1 代理模式         代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创

Spring框架——AOP(面向切面编程)详解

 1 AOP概述 ●AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是对传统 OOP(Object-Oriented Programming,面向对象编程)的补充. ●AOP编程操作的主要对象是切面(aspect),而切面模块化横切关注点. ●在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能应用在哪里,以什么方式应用,并且不必修改受影响的类.这样一来横切关注点就被模块化到特殊的类里--这样的类我们通常称之为"切面".

Spring面向切面编程(AOP)

1 spring容器中bean特性 Spring容器的javabean对象默认是单例的. 通过在xml文件中,配置可以使用某些对象为多列. Spring容器中的javabean对象默认是立即加载(立即实例化:spring加载完成,立即创建对象) scope:属性 singleton:默认值为单例,默认也是立即加载,在加载完成spring容器的时候,bean对象已经创建完成 prototype:多例的,默认懒加载,spring容器加载完成的时候,不会创建bean的对象,只有从容器获得bean对象的

使用spring方式来实现aop编程

1:什么是aop? Aspect Oriented Programming 面向切面编程 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 面向对