一.什么是面向切面
AOP 是Aspect-Oriented Programming的简称,意思是面向切面编程。AOP是对OOP的补充和完善。比如刚才的问题,程序中所有的业务方法都需要日志记录、参数验证、事务处理,这些公共的处理如果放在每个业务方法里,系统会变的臃肿,而且很难去维护。散布在系统各处的需要在实现业务系统时关注的事情就被成为“切面”,也称为关注点,AOP的思想就是把这些公共部分从业务方法中提取出来,集中处理。
| 设置切面 |
| 设置切点 |
| 引入增强bean |
| 异常增强 |
| 后置增强 |
| 前置增强 |
| 环绕增强 |
<!--配置切点-->
<!--对哪一个类或者哪一个方法进行值的注入,第二个参数是对哪一个类进行值的注入-->
<!--(* com.offcn.service.UserService.*(..))代表userService所有方法-->
<aop:pointcut id="pointcut" expression="execution(* com.offcn.service.UserService.*(..))"></aop:pointcut>
<!--引入方法的增强bean-->
<aop:aspect ref="aopError">
<!--在这个里面也就可以配置你的异常后置增强,这个方法必须引入你的增强bean的方法-->
<!--第二个参数是设置切点-->
<aop:after-throwing method="afterError" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
<!--环绕增强 相当于一个前置+一个后置-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
<!--配置切点-->
<!--对哪一个类或者哪一个方法进行值的注入,第二个参数是对哪一个类进行值的注入-->
<!--(* com.offcn.service.UserService.*(..))代表userService所有方法-->
<aop:pointcut id="pointcut" expression="execution(* com.offcn.service.UserService.*(..))"></aop:pointcut>
<!--引入方法的增强bean-->
<aop:aspect ref="aopError">
<!--在这个里面也就可以配置你的异常后置增强,这个方法必须引入你的增强bean的方法-->
<!--第二个参数是设置切点-->
<aop:after-throwing method="afterError" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
<!--环绕增强 相当于一个前置+一个后置-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
二.面向切面的编程
面向切面原生态开发(需要自己配置xml)
这个原生态的增强bean
package com.offcn.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import java.util.Arrays;
public class AopError {
/*JoinPoint这个类封装了所有动态代理的类的信息*/
public void afterError(JoinPoint joinpoint, RuntimeException e){
System.out.println(joinpoint.getSignature().getName()+"这个方法的异常信息"+e.getMessage());
}
public void after(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName());
}
/*环绕增强 传递的是JoinPoint的一个子类ProceedingJoinPoint*/
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println(proceedingJoinPoint.getTarget()+Arrays.toString(proceedingJoinPoint.getArgs()));
try {
//调用此方法执行目标对象的相应方法,这个方法相当于一个分割线,
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println(proceedingJoinPoint.getSignature().getName());
}
}
package com.offcn.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import java.util.Arrays;
public class AopError {
/*JoinPoint这个类封装了所有动态代理的类的信息*/
public void afterError(JoinPoint joinpoint, RuntimeException e){
System.out.println(joinpoint.getSignature().getName()+"这个方法的异常信息"+e.getMessage());
}
public void after(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName());
}
/*环绕增强 传递的是JoinPoint的一个子类ProceedingJoinPoint*/
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println(proceedingJoinPoint.getTarget()+Arrays.toString(proceedingJoinPoint.getArgs()));
try {
//调用此方法执行目标对象的相应方法,这个方法相当于一个分割线,
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println(proceedingJoinPoint.getSignature().getName());
}
}
这是原生态.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-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!--配置dao层-->
<bean id="userDao" class="com.offcn.dao.impl.UserDaoImpl"></bean>
<!--配置service层-->
<bean id="userService" class="com.offcn.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!--配置增强的bean-->
<bean id="aopError" class="com.offcn.aop.AopError"></bean>
<!--设置切面-->
<aop:config>
<!--配置切点-->
<!--对哪一个类或者哪一个方法进行值的注入,第二个参数是对哪一个类进行值的注入-->
<!--(* com.offcn.service.UserService.*(..))代表userService所有方法-->
<aop:pointcut id="pointcut" expression="execution(* com.offcn.service.UserService.*(..))"></aop:pointcut>
<!--引入方法的增强bean-->
<aop:aspect ref="aopError">
<!--在这个里面也就可以配置你的异常后置增强,这个方法必须引入你的增强bean的方法-->
<!--第二个参数是设置切点-->
<!-- <aop:after-throwing method="afterError" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>-->
<!--后置增强-->
<!-- <aop:after method="after" pointcut-ref="pointcut"></aop:after>-->
<!--前置增强-->
<!-- <aop:before method=""></aop:before>-->
<!--环绕增强 相当于一个前置+一个后置-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
</beans>
有注解的是已经包装过得(xml中就不需要再自己配置)
这是使用注解的增强bean
package com.offcn.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import java.util.Arrays;
@Aspect
public class AopError {
/*这个类封装了所有动态代理的类的信息*//*
//expression="execution(* com.offcn.service.UserService.*(..)
//@AfterThrowing(pointcut = "(* com.offcn.service.UserService.*(..))",throwing = "e")
public void afterError(JoinPoint joinpoint, RuntimeException e){
System.out.println(joinpoint.getSignature().getName()+"这个方法的异常信息"+e.getMessage());
}
public void after(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName());
}
*/
/*环绕增强 传递的是其JoinPoint子类ProceedingJoinPoint*/
@Around("execution(* com.offcn.service.UserService.*(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println(proceedingJoinPoint.getTarget()+ Arrays.toString(proceedingJoinPoint.getArgs()));
/*调用此方法执行目标对象相应的方法*//**//*这个方法又相当于一个分割线,也就是前置与后置的分割线*/
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
} System.out.println(proceedingJoinPoint.getSignature().getName());
}
}
//需要添加的jar包
aopalliance-1.0.jar
aspectjweaver-1.6.9.jar
cglib-nodep-3.1.jar
commons-logging-1.2.jar
junit-4.10.jar
log4j-1.2.17.jar
spring-aop-3.2.13.RELEASE.jar
spring-beans-3.2.13.RELEASE.jar
spring-context-3.2.13.RELEASE.jar
spring-core-3.2.13.RELEASE.jar
spring-expression-3.2.13.RELEASE.jar
package com.offcn.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import java.util.Arrays;
@Aspect
public class AopError {
/*这个类封装了所有动态代理的类的信息*//*
//expression="execution(* com.offcn.service.UserService.*(..)
//@AfterThrowing(pointcut = "(* com.offcn.service.UserService.*(..))",throwing = "e")
public void afterError(JoinPoint joinpoint, RuntimeException e){
System.out.println(joinpoint.getSignature().getName()+"这个方法的异常信息"+e.getMessage());
}
public void after(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName());
}
*/
/*环绕增强 传递的是其JoinPoint子类ProceedingJoinPoint*/
@Around("execution(* com.offcn.service.UserService.*(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println(proceedingJoinPoint.getTarget()+ Arrays.toString(proceedingJoinPoint.getArgs()));
/*调用此方法执行目标对象相应的方法*//**//*这个方法又相当于一个分割线,也就是前置与后置的分割线*/
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
} System.out.println(proceedingJoinPoint.getSignature().getName());
}
}
//需要添加的jar包
aopalliance-1.0.jar
aspectjweaver-1.6.9.jar
cglib-nodep-3.1.jar
commons-logging-1.2.jar
junit-4.10.jar
log4j-1.2.17.jar
spring-aop-3.2.13.RELEASE.jar
spring-beans-3.2.13.RELEASE.jar
spring-context-3.2.13.RELEASE.jar
spring-core-3.2.13.RELEASE.jar
spring-expression-3.2.13.RELEASE.jar
这是使用注解的.XML文件,多了三个AOP的头
<?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:context="http://www.springframework.org/schema/context"
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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<context:component-scan base-package="com.offcn.service,com.offcn.dao" />
<bean class="com.offcn.aop.AopError"></bean>
<!--开启spring注解-->
<aop:aspectj-autoproxy/>
</beans>
注解的解释:
@Aspect :注解表示这是一个切面
@AfterThrowing:注解表示异常增强
@AfterThrowing(pointcut = "(* com.offcn.service.UserService.*(..))",throwing = "e")
@AfterThrowing(pointcut = "(* com.offcn.service.UserService.*(..))",throwing = "e")
@After @Before @Around:注解表示后置,前置,环绕增强
//execution表示切入点指示符
@After("execution(* com.offcn.service.UserService.*(..))")
@Before("execution(* com.offcn.service.UserService.*(..))")
@Around("execution(* com.offcn.service.UserService.*(..))")
//execution表示切入点指示符
@After("execution(* com.offcn.service.UserService.*(..))")
@Before("execution(* com.offcn.service.UserService.*(..))")
@Around("execution(* com.offcn.service.UserService.*(..))")