连接点(Joinpoint)(要被拦截的方法):并不是所有被spring管理的对象的所有方法都是连接点,在Spring
AOP中,一个连接点总是表示一个方法的执行。
切入点:使用表达式,哪些切入点需要被切入。
切面:一个关注点的模块化,这个关注点可能会横切多个对象。就是要拦截的类。
织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。切点把切面织入进来。
通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知
目标对象(Target
Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。被代理对象,实际对象
(切面上的通知)
当连接点被调用时,告知切入点要切入哪个方法,引入切面,切面拦截,然后去通知。
例子:导入aopalliance.jar、aspectjweaver.jar
beans.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:tx="http://www.springframework.org/schema/tx"
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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-lazy-init="false" default-autowire="no">
<bean id="Myservice" class="org.hzy.services.MyService"/>
<bean id="MyAdvice" class="org.hzy.advices.MyAdvice"/>
<aop:config><!-- 只需要一个就可以包含多个切面 -->
<aop:pointcut id="before" expression="execution(* org.hzy.services.MyService.add_user(..))"/><!-- 顶级切点 -->
<aop:pointcut id="around" expression="execution(* org.hzy.services.MyService.add(Integer,String))"/>
<aop:aspect ref="MyAdvice"><!-- 一个切面包含多个通知 -->
<aop:before method="doBefore" pointcut-ref="before"/>
<!-- <aop:after method="doAfter" pointcut-ref="before"/>-->
<!-- returning 注册变量来接收方法的返回值 -->
<aop:after-returning method="doAfter" pointcut="execution(* org.hzy.services.MyService.add())" returning="ss" />
<!-- throwing 注册变量来接收方法产生的异常-->
<aop:after-throwing throwing="ex" pointcut="execution(* org.hzy.services.MyService.add(Integer))" method="doThrow"/>
<aop:around method="doAround" pointcut-ref="around"/>
</aop:aspect>
</aop:config>
</beans>
传参数还可以用args,在表达式里面 在通知中args-name
自定义异常类Myexception.java
package org.hzy.exceptions;
public class MyException extends Exception{//自定义异常
public MyException(String msg){
super(msg);
}
}
IMyService.java
package org.hzy.services;
import org.hzy.exceptions.MyException;
public interface IMyService { //实现接口的方法才是连接点
public void add_user(String uname);
public String add();
public void add(Integer i) throws MyException;
public void add(Integer i,String uname);
}
MyService.java
package org.hzy.services;
import org.hzy.exceptions.MyException;
public class MyService implements IMyService{
public void add_user(String uname){
System.out.println("add_user!!!!!!"+uname);
}
public String add(){
System.out.println("add!!!!!!!!!!!");
return "hzy";
}
public void add(Integer i) throws MyException{//声明异常
System.out.println("add with args i!!!!!!!!!!!");
String a=null;
// try { //在这里捕获异常后将不会走拦截方法
// System.out.println(a.equals(i));
// } catch (Exception e) {
// // TODO: handle exception
// }
throw new MyException("wrong!!!!!!!!!!");
// System.out.println(a.equals(i));
}
public void add(Integer i,String uname){
System.out.println("this is add with args uname"+i+" "+uname);
}
}
MyAdvice.java(切面类)
package org.hzy.advices;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAdvice {
//前置通知不能改变参数,是只读的
public void doBefore(JoinPoint jp){
System.out.println(jp.getTarget());//得到目标对象,也是被代理对象,真正的对象
System.out.println(jp.getArgs()[0]);
System.out.println(jp.getSignature().getName());//得到方法名
System.out.println("this is doBefore");
}
//后置拦截,一般使用After-returning
public void doAfter(JoinPoint jp,Object ss){//至少两个参数,这个参数名必须是ss且是第0位
System.out.println(ss);
System.out.println("this is doAfter");
}
public void doThrow(JoinPoint jp,Exception ex){//在异常发生前调用
System.out.println(ex+" "+ex.getMessage());
System.out.println("this is doThrow");
}
//环绕通知,要手动调用,连接点被包住,使用连接点的子类ProceedingJoinPoint
public void doAround(ProceedingJoinPoint pjp) throws Throwable{//Throwable异常比exception异常高
System.out.println("this is doAround");
if(Integer.parseInt(pjp.getArgs()[0].toString())<10){//传过来的值是12,aa
System.out.println("小于10");
}else{
Object o=pjp.proceed(new Object[]{new Integer(20),"hzy"});//调用下一个,在调用连接点方法之前,可以改变值,不像前置通知,如果不改变的话,可以直接pjp.proceed();
System.out.println(o);//是null,void的返回值是null
}
}
}
自定义异常将会把异常消息被异常通知拦截
MyTest.java
package org.hzy.test;
import org.hzy.exceptions.MyException;
import org.hzy.services.IMyService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest1 {
public static void main(String[] args) throws MyException {
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans1.xml");
// MyService my=ctx.getBean("Myservice",MyService.class);//Add CGLIB to the class path or specify proxy interfaces
IMyService my=ctx.getBean("Myservice",IMyService.class);//由于返回的是代理,代理与MyService不相干,不能转换,所有要实现接口
// my.add_user("hzy");
// my.add();
// my.add(1);
/* try {
my.add(1);
} catch (Exception e) {
// TODO: handle exception
System.out.println("错误!!!!!!!!!!!");//会先走拦截方法
}*/
my.add(12,"aa");
}
}
注:new
出来的是不会别切入拦截的,要spring中的
当没有实现接口的时候,报错,增加CGLIB包或者增加代理接口
Spring发现被切入的对象实例,返回的是代理,所以通过getBean得到的是代理($proxy)
向Spring容器要MyService对象,却返回个代理,这个代理和MyService对象不相关,不能转换,所以实现接口,代理也实现接口。所以,
接口中的方法才是真正的接入点。
动态代理:(因为编译好的类是不能修改的,所以需要代理)
MyServiceProxy也实现了接口,里面有MyService这个属性,当被切入拦截的时候,在代理的add_user()中,
MyService
mys;是Spring产生的
public
void add_user(String name){
加了拦截的代码
mys.add_user(name);
}
分享到:
相关推荐
这个简单例子将帮助我们理解AOP的基本概念和如何在Spring框架中实现它。 首先,我们要知道AOP的核心概念:切面、通知、连接点、切点、目标对象和代理。切面是包含横切关注点(如日志记录、事务管理等)的模块化组件...
通过阅读`Test`类,你可以看到如何设置测试场景并触发AOP通知。 总结一下,Spring AOP提供了一种优雅的方式来处理系统的横切关注点,如日志记录、事务管理或性能监控。通过定义切点、创建切面和配置通知,我们可以...
现在,我们来看如何创建一个简单的Spring AOP例子: 1. **定义切面(Aspect)**:切面是包含通知(Advice)和切入点(Pointcut)的类。通知定义了要执行的逻辑,切入点定义了何时执行。例如,我们可以创建一个名为`...
- **注解驱动的AOP**:通过在类或方法上使用特定的注解(如`@Aspect`, `@Before`, `@After`, `@Around`, `@Pointcut`等)来声明切面和通知。 3. **示例源码解析** - `aopDemo`项目中,通常会包含一个`Aspect`类,...
在本例子中,我们将探讨如何使用Spring框架实现AOP来记录日志。 **一、AOP概念** AOP(Aspect Oriented Programming)的核心是切面(Aspect),它将分散在多个对象中的共同行为(如日志、异常处理)抽象出来,形成...
通常,AOP的例子会包括创建一个切面、定义通知(advice)、指定切入点(pointcut)以及如何把这些元素编织(weaving)到应用程序中。 在AOP中,"切面"是封装了特定关注点的模块,它包含通知和切入点。"通知"是在...
AOP通知是指在特定连接点(Join Point)执行的动作,Spring支持五种不同的通知类型: 1. **前置通知(Before Advice)**: 在目标方法执行之前运行。 2. **后置通知(After Advice)**: 在目标方法执行之后运行,...
在这个"SpringAOP的例子"中,我们将深入探讨如何在Eclipse环境下利用Spring AOP和动态代理来实现这些功能。 首先,让我们理解什么是AOP。AOP是一种编程范式,旨在减少代码的重复性和增强可维护性。在传统的OOP中,...
这个"springAOP演示例子"很可能会包含一个简单的Spring项目,展示如何创建和配置切面,定义切入点和通知,并观察其在实际代码中的工作原理。通过深入理解和实践这个例子,你可以更好地掌握Spring AOP的使用,提升你...
下面是一个简单的Spring MVC中AOP的例子,分为配置和实现两部分。 ### 配置 1. 在`spring-common.xml`配置文件中,我们需要引入AOP相关的命名空间,并声明一个`<aop:aspectj-autoproxy>`元素。这会告诉Spring容器...
**Spring AOP 注解例子详解** 在 Spring 框架中,面向切面编程(Aspect Oriented Programming,AOP)是一种强大的设计模式,它允许我们分离关注点,将业务逻辑与系统服务(如日志、事务管理等)解耦。在 Spring AOP...
在本文中,我们将深入探讨Spring AOP的基本概念、工作原理以及如何通过一个简单的例子来实现它。 AOP的核心概念包括切面(Aspect)、连接点(Join Point)、通知(Advice)、引入(Introduction)、目标对象...
- SpringAOP:这个例子将演示如何在Spring中实现AOP。可能包含了一些切面、通知和切入点的定义,以及如何将它们应用到目标对象上。这将帮助你理解AOP的工作原理以及如何在实际项目中使用。 通过这三个例子,你可以...
要创建一个Spring AOP的例子,我们首先需要定义一个切面类,它可能包含一个或多个通知方法。然后,我们需要定义切入点表达式,这可以使用`@Pointcut`注解完成。接下来,我们可以使用`@Before`, `@After`, `@Around`,...
在这个经典例子中,我们将深入理解Spring AOP的核心概念,并通过实际操作来加深印象。 首先,AOP的核心是切面(Aspect),它封装了横切关注点,如日志记录、事务管理等。在Spring AOP中,切面通常由一个或多个通知...
在本示例中,我们将深入探讨Spring框架的3.1版本中的核心概念之一:面向切面编程(Aspect-...通过学习和理解这个简单的例子,我们可以更好地掌握这一关键特性,并将其应用于实际项目中,提升软件的质量和可维护性。
这个例子"AOP+Sample"将展示如何在实际项目中应用AOP。通常,AOP的实现依赖于一些框架,如Spring框架在Java中的实现。下面我们将深入探讨AOP的核心概念和操作步骤: 1. **切面(Aspect)**:切面是AOP的核心,它...
通过这个"Aop例子 demo",开发者可以学习如何定义切面、切入点和通知,以及如何将它们应用到实际的应用程序中。实践操作比理论学习更能帮助开发者掌握AOP的实际应用,因此这个示例项目是一个很好的起点。
标题提到的"Spring 使用AspectJ 实现 AOP之前置通知小例子",指的是利用AspectJ在Spring中实现AOP的一种特定类型的通知——前置通知(Before advice)。前置通知在目标方法执行之前运行,但不会阻止方法的执行。这种...
这个例子旨在帮助我们理解和应用Spring框架的AOP特性。以下是对该主题的详细解释: 一、Spring AOP概述 Spring AOP提供了一种模块化和声明式的方式来实现横切关注点,如日志记录、事务管理、性能监控等。它通过切面...