大家好,我是IT修真院深圳分院第12期的JAVA学员,一枚正直纯洁善良的java程序员。
今天给大家分享一下,修真院官网Java任务3,深度思考中的知识点—Spring Aop?
1.背景介绍
1、什么是AOP
1)在OOP(面向对象编程)中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加。
2)AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为“切面”(Aspect)
3)切面将那些与业务无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性、提高了开发的效率和程序的可复用性。
2、AOP与OOP的区别
1)AOP可以说是OOP(面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。
2)不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系
3)例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting)。
4)在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
3、AOP的思想
1) AOP的核心思想是帮助我们在扩展功能(方法)时可以不依靠修改源代码来实现。
2)其采取横向抽取机制,规避了传统面向对象中纵向继承体系的重复性高耦合代码。
2.知识剖析
1、为什么要使用aop
1)为了方便,用了aop能让你少写很多代码
2)为了更清晰的逻辑,可以让你的业务逻辑去关注自己本身的业务,而不去想一些其他的事情,这些其他的事情包括:安全,事物,日志等。
3)为了降低之前传统面向对象中采用纵向继承体系增强方法导致的耦合度过高的问题:
4)提高了代码的复用性
2、浅析AOP思想的发展及原理
发展:修改源代码————采用OOP纵向继承体系————采用AOP横向织入
实现原理:通过动态代理创建代理对象来实现,默认使用Java动态代理来创建AOP代理,当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理
3、aop专业术语
1.通知(Advice):通知定义了切面是什么以及何时使用;里面就是增强方法的逻辑,分为前置增强,后置增强,环绕增强,最终增强,异常增强。
2.连接点(JoinPoint):连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,并添加新的行为。
3.切入点(Pointcut)*:切点有助于缩小切面所通知的连接点的范围。(何处)
4.切面(Aspect)*:切面是通知和切点的结合。通知和切点定义了切面的全部内容——它是什么,在何时何处完成其功能。
5.目标(target):被增强的方法所在的那个类,也就是真正的业务逻辑,他可以在毫不知情的情况下,被织入切面。而自己专注于业务本身的逻辑。
6.代理(proxy):目标类被增强后产生的代理类
7.织入(weaving):把增强应用到目标类的过程
8:引入(Introduction) 引入允许我们向现有的类添加新方法或属性,从而无需修改这些现有类的情况下,让他们具有新的行为和状态
4、通知类型介绍
(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名 来访问目标方法中所抛出的异常对象
(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint
3、常见问题
1、实现AOP的方式有哪些?
2、实现增强的方法有那些?
3、在确定好需要增强的方法之后,切入点的定位是如何完成的
4、使用@Aspect对SSM进行切入,统计运行时间。
4.解决方案
1):实现AOP的方式有哪些?
在sring里面进行aop操作,使用aspectJ(AspectJ是一种扩展Java)来实现。aspectJ本身是一个单独的面向切面的框架,里面定义了AOP语法,不是spring的一部分,和spring协同完成springAOP的操作,使用aspectJ来实现springAOP的操作有两种方式
1:继承的类的方式(不推荐)
2:基于aspectJ的xml文件
3.基于aspectJ注解
2):实现增强的方法有那些?
织入
引入
3):在确定好需要增强的方法之后,切入点的定位是如何完成的
可以用execution表达式来解决(常用)
也可以用xml配置,使用RegexpMethodPointcutAdvisor,来定义切点。
1.execution(* com.aop.add(..))
2.匹配所有save开头的方法:execution(* save*(..))
4):使用@Aspect对SSM进行切入,统计运行时间。
在编码实战的时候讲讲。
5.编码实战
基于xml配置文件配置
需要创建aop对象,设置切入点、增强类、方法等。
基于注解方式配置文件
<context:component-scan base-package="anno"/>
<aop:aspectj-autoproxy />
注意这里尽可能使用闭合标签,不要使用,否则无法正常切入<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
这里上传一个简单的基于注解方式的aop demo
applicationContext.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: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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="anno"/>
<aop:aspectj-autoproxy />
</beans>
UserService.java
package anno;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void add(){
System.out.println("UserService add()");
}
public boolean delete(){
System.out.println("UserService delete()");
return true;
}
public void edit(){
System.out.println("UserService edit()");
int i = 5/0;
}
}
Operator.java
package anno;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class Operator {
@Pointcut("execution(* anno..*.*(..))")
public void pointCut(){}
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint){
System.out.println("AOP Before Advice...");
}
@After("pointCut()")
public void doAfter(JoinPoint joinPoint){
System.out.println("AOP After Advice...");
}
@AfterReturning(pointcut="pointCut()",returning="returnVal")
public void afterReturn(JoinPoint joinPoint,Object returnVal){
System.out.println("AOP AfterReturning Advice:" + returnVal);
}
@AfterThrowing(pointcut="pointCut()",throwing="error")
public void afterThrowing(JoinPoint joinPoint,Throwable error){
System.out.println("AOP AfterThrowing Advice..." + error);
System.out.println("AfterThrowing...");
}
@Around("pointCut()")
public void around(ProceedingJoinPoint pjp){
System.out.println("AOP Aronud before...");
try {
pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("AOP Aronud after...");
}
}
Test.java
package anno;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.add();
}
}
运行结果
扩展思考
1、 基于注解与基于配置文件的优缺点.
优点:
注解能减少配置的工作,而且配置信息和JAVA代码放在一起,有助于增强程序的内聚性。相对于XML配置文件进行配置文件和程序文件的切换,用注解方式,能提高开发的连贯性,和提成开发效率。
缺点:
程序复杂的话,还是使用xml配置文件的方式,这样可读性和可维护性比较强。
- 参考文献
https://www.cnblogs.com/liuru...
https://www.cnblogs.com/hongw...
https://blog.csdn.net/zghwaic...
-
更多讨论
1、 基于注解与基于配置文件的优缺点有哪些?
优点: 注解能减少配置的工作,而且配置信息和JAVA代码放在一起,有助于增强程序的内聚性。相对于XML配置文件进行配置文件和程序文件的切换,用注解方式,能提高开发的连贯性,和提成开发效率。 缺点: 程序复杂的话,还是使用xml配置文件的方式,这样可读性和可维护性比较强。
2、实现AOP的方式有哪些?
在sring里面进行aop操作,使用aspectJ(AspectJ是一种扩展Java)来实现。aspectJ本身是一个单独的面向切面的框架,里面定义了AOP语法,不是spring的一部分,和spring协同完成springAOP的操作,使用aspectJ来实现springAOP的操作有两种方式
1:继承的类的方式(不推荐)
2:基于aspectJ的xml文件
3.基于aspectJ注解
3、实现增强的方法有那些?
织入
引入
两种方式
今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。