① 导入AOP相关的坐标
② 创建目标接口和目标类
③ 创建切面类(内部有增强方法)
④ 将目标类和切面类的对象创建权交给Spring
⑤ 在applicationContext中配置织入关系
⑥ 测试代码
1)快速入门:
① 首先我们先在pom.xml里面导入AOP相关的坐标
org.springframework
spring-context
5.0.5.RELEASE
org.aspectj
aspectjweaver
1.8.4
junit
junit
4.11
② 然后我们编写目标类和目标方法
package Demo.XML.AOP.Impl;
import Demo.XML.AOP.Target;
public class TargetImpl implements Target {
public void say() {
System.out.println("我是张三...");
}
}
③编写切面方法
package Demo.XML.AOP;
public class Advice {
public void before(){
System.out.println("你好!!!");
}
public void afterReturning(){
System.out.println("你好啊,张三。我是李四。");
}
}
④测试代码
package Demo.XML.AOP;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
Target target = (Target) app.getBean("target");
target.say();
}
}
⑤配置Spring容器
<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 id="target" class="Demo.XML.AOP.Impl.TargetImpl">bean>
<bean id="myAspect" class="Demo.XML.AOP.Advice">bean>
<aop:config>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut="execution(public void Demo.XML.AOP.Impl.TargetImpl.say())"/>
<aop:after-returning method="afterReturning" pointcut="execution(public void Demo.XML.AOP.Impl.TargetImpl.say())"/>
aop:aspect>
aop:config>
beans>
2)切点表达式的写法:
表达式的语法如下:
execution([修饰符]返回值类型 包名.类名.方法名(参数))
访问修饰符可以省略
返回值类型,包名,类名,方法名可以使用*来表示任意的
包名与类名之间的一个点,代表当前包下的类,两个点…代表当前包下及其子包下的类
参数列表可以使用两个点…来表示任意个数以及任意类型的参数列表
例如:
execution(public void Demo.XML.AOP.Impl.TargetImpl.*(..))
3)通知的类型:
通知的配置语法:
<aop:通知类型 method="切面类中方法名" pointcut="切点表达式">aop:通知类型>
名称 | 标签 | 说明 |
---|---|---|
前置通知 | 用于配置前置通知。指定增强的方法在切入点方法之前执行 | |
后置通知 | 用于配置后置通知。指定增强的方法在切入点方法之后执行 | |
环绕通知 | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 | |
异常抛出通知 | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 | |
最终通知 | 用于配置最终通知。无论增强方式执行是否有异常,都会执行 |
这里我们需要注意的是环绕通知的写法
//Proceeding JoinPoint: 正在执行的连接点也就是我们所说的切点
public Object around(PreceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕前...");
Object proceed = pjp.proceed();
System.out.println("环绕后...");
return proceed;
}
4)切点表达式的抽取:
当我们对多个切点使用相同的切点表达式进行增强的话,我们可以将切点表达式进行抽取,在增强中使用 pointcut-ref属性来替代原来的pointcut属性,这样便于我们后期进行代码的维护。
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut id="myPointcut" expression="execution(* Demo.XML.Impl.TargetImpl.*(..))"/>
<aop:before method="before" pointcut-ref="myPointcut">aop:before>
aop:aspect>
aop:config>
织入配置
<aop:config>
<aop:aspect ref="切面类">
<aop:before method="通知方法名称" pointcut="切点表达式">aop:before>
aop:aspect>
aop:config>
通知的类型分为前置通知,后置通知,环绕通知,异常抛出通知,最终通知
切点表达式的写法:
execution([修饰符]返回值类型 包名.类名.方法名(参数名))
① 创建目标接口和目标类,其内部有切点
② 创建切面类,其内部有增强方法
③ 将目标类和切面类的对象创建权交给spring
④ 在切面类中使用注解配置织入关系
⑤ 在配置文件中开启组件扫描和AOP的自动代理
⑥ 测试代码
1)快速入门:
① 创建目标类和目标方法
package Demo.XML.AOP.Impl;
import Demo.XML.AOP.Target;
public class TargetImpl implements Target {
public void say() {
System.out.println("我是张三...");
}
}
② 创建切面类,其内部有增强方法
package Demo.XML.AOP;
public class Advice {
public void before(){
System.out.println("你好!!!");
}
public void afterReturning(){
System.out.println("你好啊,张三。我是李四。");
}
}
③ 将目标类和切面类的对象创建权交给spring
<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"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="target" class="Demo.XML.AOP.Impl.TargetImpl">bean>
<bean id="myAspect" class="Demo.XML.AOP.Advice">bean>
beans>
④ 在切面类中使用注解配置织入关系(也就是添加注解)
package Demo.XML.AOP;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class Advice {
@Before("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
public void before(){
System.out.println("你好!!!");
}
@AfterReturning("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
public void afterReturning(){
System.out.println("你好啊,张三。我是李四。");
}
@Around("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("你好啊");
Object proceed = pjp.proceed();
System.out.println("我是李四");
return proceed;
}
}
⑤ 在配置文件中开启组件扫描和AOP的自动代理
<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"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="target" class="Demo.XML.AOP.Impl.TargetImpl">bean>
<bean id="myAspect" class="Demo.XML.AOP.Advice">bean>
<context:component-scan base-package="Demo.XML.AOP">context:component-scan>
<aop:aspectj-autoproxy/>
beans>
⑥ 测试代码
package Demo.XML.AOP;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
Target target = (Target) app.getBean("target");
target.say();
}
}
2)注解通知的类型:
通知配置的基本语法:@通知注解(“切点表达式”)
名称 | 注解 | 说明 |
---|---|---|
前置通知 | @Before | 用于配置前置通知。指定增强的方法在切入点方法之前执行 |
后置通知 | @AfterReturning | 用于配置后置通知。指定增强的方法在切入点方法之后执行 |
环绕通知 | @Around | 用于配置环绕通知。 指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知 | @AfterThrowing | 用于配置异常抛出通知。指定增强的方法在出现异常时执行 |
最终通知 | @After | 用于配置最终通知。无论增强方法执行是否有异常都会执行 |
3)注解通知的类型:
通过上面的步骤我也不能发现一个问题,就是切点表达式复用的问题,与xml配置aop一样我们也可以把切点表达式抽取出来。
抽取方法:
在切面类中定义一个切点表达式的方法。在该方法上面使用@Pointcut注解定义切点表达式,然后在在增强注解中进行引用,具体代码如下:
package Demo.XML.AOP;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class Advice {
@Before("Advice.mypoint()")
public void before(){
System.out.println("你好!!!");
}
@AfterReturning("Advice.mypoint()")
public void afterReturning(){
System.out.println("你好啊,张三。我是李四。");
}
@Around("Advice.mypoint()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("你好啊");
Object proceed = pjp.proceed();
System.out.println("我是李四");
return proceed;
}
@Pointcut("execution(public void Demo.XML.AOP.Impl.TargetImpl.say())")
public void mypoint(){
}
}
基于注解方式的aop开发步骤
使用@Aspect标注切面类
使用@通知注解标注通知方法
在配置文件中配置aop自动代理
<aop:aspectj-autoproxy/>