spring-第二章-AOP
一,回顾
1.控制反转(IOC)
以前创建对象,由我们自己决定,现在我们把管理对象的声明周期权力交给spring;
2.依赖注入(DI)
A对象需要B对象的支持,spring就把B注入给A,那么A就拥有了B;
底层通过反射技术实现(Class字节码)
3.具体实现
(1)实体类
(2)把实体类注册到xml配置文件中
(3)通过context上下文对象(spring容器)获取进行使用
二,AOP简介
AOP(Aspect Oriented Programming) 面向切面编程(横向);
OOP面向对象编程(纵向编程)
AOP技术利用"横切",解刨开封装的对象内容,将那些影响了多个类的公共行为封装到一个可重用的模块,并将其命名为"Aspect",即切面,切面就是与主业务无关,却为主业务模块提供额外的扩展,便于减少系统代码的重复性,降低模块之间的耦合性,并利于系统的可操作性和维护性;
AOP底层使用代理技术实现,代理内部有反射技术的影子
三AOP基本概念
1.Aspect(切面)
通常是一个类,里面可以定义切入点和通知
2.JoinPoint(连接点)
被拦截的点,因为spring只支持方法类型的连接点,所以在spring中连接点指定就是被拦截的方法,实际上连接点还可以是字段或者构造器
3.advice(通知)
指拦截到的连接点(方法)之后要执行的增强代码,通知分为:前置,后置,异常,最终,环绕通知(before,after,afterThrowing,afterReturing,around)
4.pointcut(切入点)
对连接点(方法)进行拦截的定义,在程序主要体现为输入切入点表达式
5.tarage(目标对象)
代理的目标对象
6.proxy(代理)
AOP框架自动创建的代理对象
四,spring aop基于xml方式实现
1,添加依赖
- <!-- spring-context -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>5.1.0.RELEASE</version>
- </dependency>
- <!-- aop依赖的jar包 -->
- <!-- aspectjweaver -->
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.9.2</version>
- </dependency>
- <!--aspectjrt -->
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.2</version>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.2</version>
- <scope>provided</scope>
- </dependency>
2、UserServiceImpl业务类
- public class UserServiceImpl {
- public boolean delete(int id){
- System.out.println("UserServiceImpl.delete..."+id);
- return true;
- }
3、TranAop切面类
此类为切面类,给业务层类中方法添加增强代码
- public class TranAop {
- //前置通知
- public void before(){
- System.out.println("TranAop.before...");
- }
- //返回值后通知
- public void afterReturning(){
- System.out.println("TranAop.afterReturning...");
- }
- //异常通知
- public void afterThrowing(Exception ex){
- System.out.println("TranAop.afterThrowing..."+ex.getMessage());
- }
- //后置通知(最终)
- public void after(){
- System.out.println("TranAop.after...");
- }
- //环绕通知
- public Object around(ProceedingJoinPoint pjp) throws Throwable{
- System.out.println("TranAop.around.start");
- Object[] args = pjp.getArgs();
- Object result = null;
- //try {
- result = pjp.proceed();//执行目标方法
- //} catch (Throwable e) {
- // System.out.println("发生异常了哦:"+e.getMessage());
- //}
- System.out.println("TranAop.around.end");
- return result;
- }
- }
4、beans.xml
我们需要再beans.xml中配置aop;需要在xml中添加头部schema文件引用
- <?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.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd">
- <!-- 声明bean -->
- <bean id="user1" class="com.yujun.maven.service.UserServiceImpl"></bean>
- <bean id="tranAop" class="com.yujun.maven.aop.TranAop"></bean>
- <!-- spring aop 配置 -->
- <aop:config>
- <!-- 声明切面类 id:唯一标识 ref:引用bean的id-->
- <aop:aspect id="myAspect" ref="tranAop">
- <!-- 声明切入点(拦截哪些方法) 拦截service包中所有类中所有方法-->
- <aop:pointcut expression="execution(* com.yujun.maven.service.*.*(..))" id="myPointcut"/>
- <!-- 实际开发中,下面5中通知,根据实际情况进行合理的选中,不是说像我们现在这样5种都配置 -->
- <!-- 前置通知 method:切面类中的方法名-->
- <aop:before method="before" pointcut-ref="myPointcut"/>
- <!-- 后置通知 -->
- <aop:after method="after" pointcut-ref="myPointcut"/>
- <!-- 最终通知 -->
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
- <!-- 异常通知 throwing:是切面类中方法的形参名-->
- <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="ex"/>
- <!-- 环绕通知 -->
- <aop:around method="around" pointcut-ref="myPointcut"/>
- </aop:aspect>
- </aop:config>
- </beans>
5、测试
- public class Demo1 {
- public static void main(String[] args) {
- //context上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
- UserServiceImpl bean = context.getBean("user1", UserServiceImpl.class);
- bean.delete(10);
运行后的控制台输出结果:
TranAop.before...
TranAop.around.start
UserServiceImpl.delete...10
TranAop.around.end
TranAop.afterReturning...
TranAop.after...
可以看到在目标方法UserServiceImpl.delete的前后有额外的输出语句,也就表名之前我们的aop配置生效;
这里没有看到有关于异常通知的输出,原因是我们目标方法delete没有发生异常,所以就不会执行异常通知;
若想看到异常通知被执行,只需要在目标方法中添加一个可以触发异常的语句即可,当前前提是我们的环绕通知中没有对目标方法进行异常处理;
五,springaop基于注解的方式实现
下面我们使用注解方式来实现aop技术,相对来说注解方式比xml配置更简洁,所以现在实际开发中我们都会优先考虑使用注解方式;
1、AserviceImpl业务类
业务类,我们通常会统一放在service包中;
- public class AServiceImpl {
- public int m1(String s){
- System.out.println("AServiceImpl.m1..."+s);
- return 100;
- }
- }
2、LogAop切面类
- //组件:会把当前类当做bean注册到spring容器中,等效于xml中<bean />
- @Component
- //切面类:等效于xml中的<aop:aspect />
- @Aspect
- public class LogAop {
- //切入点(拦截哪些类中的哪些方法):等效于xml中<aop:pointcut />
- @Pointcut("execution(* com.yujun.maven.service.*.*(..))")
- private void pointCut(){
- }
- //前置通知:等效于xml中<aop:before />,里面的pointCut()字符串是本类中的切入点方法
- @Before("pointCut()")
- public void before(){
- System.out.println("LogAop.before...");
- }
- //返回通知:等效于xml中<aop:after-returning />
- @AfterReturning(pointcut="pointCut()",returning="result")
- public void afterReturning(Object result){
- System.out.println("LogAop.afterReturning..."+result);
- }
- //异常通知:等效于xml中<aop:after-throwing />
- @AfterThrowing(pointcut="pointCut()",throwing="ex")
- public void afterThrowing(Exception ex){
- System.out.println("LogAop.afterThrowing..."+ex.getMessage());
- }
- //最终通知:等效于xml中<aop:after />
- @After("pointCut()")
- public void after(){
- System.out.println("LogAop.after...");
- }
- //环绕通知:等效于xml中<aop:around />
- @Around("pointCut()")
- public Object around(ProceedingJoinPoint pjp) throws Throwable{
- System.out.println("LogAop.around.start...");
- Object result = pjp.proceed();//执行目标方法
- System.out.println("LogAop.around.end..."+result);
- return result;
- }
- }
此类中我们使用很多注解,每个注解的含义都有详细的说明,这里就不多做额外的解释;
主要说一下@Component注解,次注解是spring的基础注解,被此注解标注的类会被当做组件注册到spring容器中,也就相当于之前我们在xml中配置<bean />,也就是说只要在类上标注此注解,我们就不用像之前一样在xml中使用<bean />标签注册实例了;
3、beans-anno.xml
此xml配置文件我们需要添加context的schema文件头引用
- <?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"
- 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">
- <!-- 开启扫描包:把base-package指定的包中的类中的组件注册到spring容器中-->
- <context:component-scan base-package="com.yujun.maven.aop"/>
- <!-- 为 @AspectJ标注的类提供代理-->
- <aop:aspectj-autoproxy/>
- </beans>
<context:component-scan />标签配置的作用就是开启扫包功能,它会扫描base-package属性中指定的包中所有类,然后把类上标注有@Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, @Configuration等注解的类注册添加到spring容器中;
<aop:aspectj-autoproxy/>标签则是为使用@AspectJ注解风格的切面类提供代理,若没有此配置,我们的目标方法时没有aop技术支持的
4、@Service注解
- //组件:业务逻辑层的组件,等效于<bean />
- @Service
- public class AServiceImpl {
- public int m1(String s){
- System.out.println("AServiceImpl.m1..."+s);
- return 100;
- }
- }
对于AserviceImpl业务类,我们之前是通过在xml中配置<bean />标签来注册实例,那么这里我们还可以选择使用@Service注解,此注解标注的类会被当做一个服务性质组件实例被注册到spring容器中,等效于xml中<bean />标签配置实例;
注意的是我们还需要在bean-anno.xml中新增一个扫包器,因为此业务类在service包中;
- <context:component-scan base-package="com.yujun.maven.service"/>
5、测试
- public class Demo2 {
- public static void main(String[] args) {
- //context上下文
- ApplicationContext context = new ClassPathXmlApplicationContext("beans-anno.xml");
- AServiceImpl a1 = context.getBean(AServiceImpl.class);
- a1.m1("admin");
- }
- }
运行之后控制台输出
LogAop.around.start...
LogAop.before...
AServiceImpl.m1...admin
LogAop.around.end...100
LogAop.after...
LogAop.afterReturning...100
可以看到我们注解版的aop技术已经成功实现,就是输出的语句顺序和执行xml方法稍微不同,但是最终的功能实现是没有差别的;
六、小结
对于上述的两种方式aop实现,需要自己下来多多测试,然后认真理解其执行流程,这样才能对aop面向切面技术有一个更深的理解和认识;
在aop注解版方式中,我们介绍的@Component和@Service两个注解以及 xml配置中的<context:component-scan />标签扫描器,我们在后面章节也就着重说明;
spring-第二章-AOP的更多相关文章
- 复习Spring第二课--AOP原理及其实现方式
AOP原理: AOP,面向方面的编程,使用AOP,你可以将处理方面(Aspect)的代码注入主程序,通常主程序的主要目的并不在于处理这些aspect.AOP可以防止代码混乱.AOP的应用范围包括:持久 ...
- Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)
前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第3章.AOP技术
第3章--AOP技术 Spring框架 - AOP概述 笔记https://my.oschina.net/hava/blog/758873Spring框架 - AOP使用 笔记https://my.o ...
- #Spring实战第二章学习笔记————装配Bean
Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...
- Spring学习指南-第二章-Spring框架基础(完)
第二章 Spring框架基础 面向接口编程的设计方法 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...
- 第05章 AOP细节
第05章 AOP细节 1.切入点表达式 1.1 作用 通过表达式的方式定位一个或多个具体的连接点. 1.2 语法细节 ①切入点表达式的语法格式 execution([权限修饰符] [返回值类型] [简 ...
- Spring官网阅读(十八)Spring中的AOP
文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...
- 《精通Spring4.x企业应用开发实战》第二章
昨天联系了一下学长,学长说这个项目因为种种原因代码比较混乱,感觉最坏的打算是从头开始写. 大概询问了一下学长和xianhua学姐的建议,又看了看网上的资料,这个项目开发的技术栈基本就是SpringBo ...
- Spring框架之AOP源码完全解析
Spring框架之AOP源码完全解析 Spring可以说是Java企业开发里最重要的技术.Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Orie ...
- Spring 3.0 AOP (一)AOP 术语
关于AOP.之前我已写过一个系列的随笔: <自己实现简单的AOP>,它的关注点在于实现.实现语言是C#,实现方式为 自定义实现 RealProxy 抽象类.重写Invoke方法,以便进行方 ...
随机推荐
- iOS学习之自定义弹出UIPickerView或UIDatePicker(动画效果)
前面iOS学习之UIPickerView控件的简单使用 用到的UIPickerView弹出来是通过 textField.inputView = selectPicker; textField.in ...
- Linux 入门知识一(附上如何解决Ubuntu的root密码问题)
.centos有拥有七个控制台,其中第一到第六个是字符界面,第七个是图形界面 切换的快捷键是ctrl+shift+fn(n为自然数) 输入tty的话,可以检查当前处于哪个控制台 如何在cent ...
- Kafka总结的一张图
- Android中Activity的四种启动方式
谈到Activity的启动方式必须要说的是数据结构中的栈.栈是一种只能从一端进入存储数据的线性表,它以先进后出的原则存储数据,先进入的数据压入栈底,后进入的数据在栈顶.需要读取数据的时候就需要从顶部开 ...
- 142. Linked List Cycle II (List; Two-Pointers)
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...
- Gson 是google解析Json的一个开源框架,同类的框架fastJson,JackJson
Gson 是google解析Json的一个开源框架,同类的框架fastJson,JackJson等等 本人fastJson用了两年,也是从去年才开始接触Gson,希望下面的总结会对博友有用,至于Gso ...
- 17. Merge Two Binary Trees 融合二叉树
[抄题]: Given two binary trees and imagine that when you put one of them to cover the other, some node ...
- noi2729 Blah数集
Blah数集 大数学家高斯小时候偶然间发现一种有趣的自然数集合Blah,对于以a为基的集合Ba定义如下: (1) a是集合Ba的基,且a是Ba的第一个元素: (2)如果x在集合Ba中,则2x+1和3x ...
- 【原创】cython and python for kenlm
未经允许不可转载 Kenlm相关知识 Kenlm下载地址 kenlm中文版本训练语言模型 如何使用kenlm训练出来的模型C++版本 关于Kenlm模块的使用及C++源码说明 加载Kenlm模块命令 ...
- bootstrap导入JavaScript插件
Bootstrap的JavaScript插件可以单独导入到页面中,也可以一次性导入到页面中.因为在Bootstrap中的JavaScript插件都是依赖于jQuery库,所以不论是单独导入还一次性导入 ...