Spring Aop 面向切面编程
1 Aop是什么?
注明(此段话引自):https://blog.csdn.net/when_less_is_more/article/details/78175891?utm_source=copy
Aspect Oriented Programming 面向切面编程。解耦是程序员编码开发过程中一直追求的。AOP也是为了解耦所诞生。
具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回到横向业务流。
AOP 在Spring框架中被作为核心组成部分之一,的确Spring将AOP发挥到很强大的功能。最常见的就是事务控制。工作之余,对于使用的工具,不免需要了解其所以然。学习了一下,写了些程序帮助理解。
2 spring AOP 可以用来干什么?
1 防止过多代码沉积 (比如记录日志等,再也不需要每个代码里面 添加记录日志代码)
2 统一组织 管理代码 拦截某些方法执行前后,做一些操作(如关闭 流,操作事务,记录日志等等), 不影响原程序。
3 实现方式
- 注解实现
通知:
就是你想要用到的功能,也就是上面说的 安全,事物,日志等。自己 先定义好,然后在想用的地方用一下。
连接点:
就是spring允许你使用通知的地方,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。
切面:
可以是具体的一个类
切点:
声明需要切入方法的定义 ,此方法不会执行
5种类型:
- Before 某方法调用之前发出通知。
- After 某方法完成之后发出通知,不考虑方法运行的结果。
- After-returning 将通知放置在被通知的方法成功执行之后。
- After-throwing 将通知放置在被通知的方法抛出异常之后。
- Around 通知包裹在被通知的方法的周围,在方法调用之前和之后发出通知。
maven依赖:
<dependencies>
<!-- spring的依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.1.RELEASE</version>
</dependency><dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.1.RELEASE</version>
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.9.RELEASE</version>
</dependency><!-- https://mvnrepository.com/artifact/springframework/spring-orm -->
<dependency>
<groupId>springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>1.2.6</version>
</dependency>
service:
public interface UseSercvice {
public String say(String name);
}
service 实现类:
@Service
public class UseSercviceImpl implements UseSercvice{
public void say() {
System.out.println("hahhaha...");
}
public String say(String name) {
System.out.println(name);
return name;
}
}
切面类:
@Component
@Aspect //声名切面
public class AspectTest {
//声名切点 : 声明需要切入方法的定义 ,此方法不会执行
@Pointcut("execution(* com.udeam.Service.*.*(..))") // 正则表达
public void pointVoid() {
System.out.println("------切点-----");
}
@Before("pointVoid()")
public void doBefor(JoinPoint joinpoint) {
//获取方法名
System.out.println("前置通知:----------切入点方法名:"+joinpoint.getSignature().getName());
}
@After("pointVoid()")
public void doAfter(JoinPoint joinpoint) {
//获取方法名
System.out.println("后置通知:-----------切入点方法名:"+joinpoint.getSignature().getName());
}
@AfterReturning(value="pointVoid()",returning="result") // 方法正常结束后执行的代码 返回通知是可以访问到方法的返回值的
public void afterReturning(JoinPoint joinPoint, Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("返回通知: method " + methodName + " 返回值: " + result);
}
@Around("pointVoid()") //之前之后都会执行
public Object around(ProceedingJoinPoint pJoinPoint){
Object[] args = pJoinPoint.getArgs();//获取参数
String name = pJoinPoint.getTarget().getClass().getName();//获取类名
System.out.println("环绕开始。。。");
System.out.println("参数:" + args.toString() + " 名字" + name);
Object proceed =null;
try {
// 控制切入点方法的执行
proceed = pJoinPoint.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
System.out.println("环绕完成。。。。");
}
return proceed;
}
@AfterThrowing("pointVoid()")
public void afterThrowing() {
System.out.println("异常执行。。。");
}
}
spring配置 文件
约束
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd "
<!-- 注解扫描 -->
<context:component-scan base-package="com.udeam.*"/>
<!-- aop 注解实现 自动代理-->
<aop:aspectj-autoproxy />
测试:
//加载springContext 配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
UseSercvice useSercvice = (UseSercvice) context.getBean("useSercviceImpl");
useSercvice.say("zs");
结果:

可能 出现的问题:
ClassNotFoundException:org.aspectj.weaver.reflect.ReflectionWorld $ ReflectionWorldExceptionClassNotFoundException:org.aspectj.weaver.reflect.ReflectionWorld $ ReflectionWorldException
缺少下面依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
2 xml实现
切面类
public class AspectTest2 {
public void pointVoid() {
System.out.println("------切点不执行-----");
}
public void doBefor() {
System.out.println("前置通知:----------");
}
public void doAfter() {
System.out.println("后置通知-------------");
}
public void doAround(ProceedingJoinPoint point) {
System.out.println("环绕通知前-------------");
try {
point.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕通知后-------------");
}
}
xml配置
<!-- 切面 -->
<bean id="aspect" class="com.udeam.aspect.AspectTest2" />
<!-- xml配置aop -->
<aop:config>
<!-- 定义切面 -->
<aop:aspect ref="aspect">
<!-- 切点 -->
<aop:pointcut id="allManagerMethod" expression="execution(* com.udeam.Service.*.*(..))"></aop:pointcut>
<!--通知-->
<aop:before method="doBefor" pointcut-ref="allManagerMethod"></aop:before>
<aop:after method="doAfter" pointcut-ref="allManagerMethod"></aop:after>
<aop:around method="doAround" pointcut-ref="allManagerMethod"></aop:around>
</aop:aspect>
</aop:config>