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方法,以便进行方 ...
随机推荐
- python+Django创建第一个项目
1.首先搭建好环境 1.1 安装pyhton,Linux系统中,python是系统自带的所以就不用安装 1.2 安装Django框架 使用pip安装: pip install django 1.3 检 ...
- 【Todo】Linux进程调度算法学习
参考这篇文章 http://blog.chinaunix.net/uid-27052262-id-3239260.html Linux支持三种进程调度策略,分别是SCHED_FIFO . SCHED_ ...
- CSS的编写规范
一.前言 如上图,页面在渲染和画图时,耗时还是比较多的,这就对我们的编写要求愈加严格. 我们有很多方法来减少上图所示的页面加载耗时的,比如 但是更多的还是在于平时的编写规范,我们需要了解浏览器,让他更 ...
- jmeter-plugins-dubbo & DevToolBox
jmeter-plugins-dubbo使用 A. 下载jmeter并安装,http://jmeter.apache.org/download_jmeter.cgi(文中使用的版本是3.3,理论上高版 ...
- 第一个Django应用程序_part3
一.概述 此文延续第一个Django应用程序part2. 官方文档:https://docs.djangoproject.com/en/1.11/intro/tutorial03/ view是Djan ...
- Qt webkitwidgets模块和webenginewidgets模块
问题 将Qt开发的程序从Qt5.5或更低的版本迁移到5.6或更高的版本时,会提示webkitwidgets是unknown module. Project ERROR: Unknown module( ...
- static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较
隐式转换(implicit conversion) ; int b; b=a; short是两字节,int是四字节,由short型转成int型是宽化转换(bit位数增多),编译器没有warning,如 ...
- 清北学堂 day6 兔子
---恢复内容开始--- [问题描述] 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3条或更多的路径与它相连,其它的兔子窝只有1条或2条路径与 ...
- vs2015 debugger,unable to attach to application iisexpress.exe
vs2015 unable to attach to application iisexpress.exe,没有可用的数据了 搞了一天也没解决...
- CALayer, CoreGraphics与CABasicAnimation介绍
今天我们来看一下CALayer.CoreGraphics和CABasicAnimation.这些东西在处理界面绘制.动画效果上非常有用. 本篇博文就讲介绍CALayer的基本概念,使用CoreGrap ...