Spring学习手札(二)面向切面编程AOP
AOP理解
Aspect Oriented Program面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
但是,这种说法有些片面,因为在软件工程中,AOP的价值体现的并不是代码方面,更多的是为了项目的模块化,而不仅仅是为了减少重复代码。
AOP是一种编程思想,为的是让模块本身变得更加内聚,让开发者更多的关注到业务逻辑的开发。
在面向切面编程里,把功能分为核心业务功能和周边业务功能:
核心业务,比如登陆,日常增,删数据
周边功能,统计,日志,事务管理。在Spring的面向切面编程AOP思想里,即被定义为切面
在面向切面的思想里,核心业务功能和切面功能单独开发,然后把两个整合在一起,就是AOP。
AOP实现原理
AOP底层将采用代理机制进行实现
接口+实现类:spring采用jdk的动态代理Proxy
实现类:spring采用cglib字节码增强
Spring默认使用JDK动态代理,在需要代理类而不是接口的时候,Spring会自动切换为使用cglib代理,不过现在的项目都是面向接口开发,所以JDK动态代理相对来说用的还是多一些。
Spring AOP引入了几个概念
切面(Aspect),它是跨不同Java类层面的横切性逻辑。可以通过XML文件中配置的普通类,也可以在类代码中使用“@Aspect” 注解去声明,在运行时,Spring会创建类似Advisor来代替它。其内部包括切入和通知。通俗的讲,是要告诉Spring什么时候,什么地方,做什么。
连接点(JoinPoint),程序运行过程中明确的点,一般是方法的调用。
通知(Advice),AOP在特定的切入点上知性的增强处理,告诉Spring什么时候,做什么。一般会讲Advice模拟成一个拦截起,并且在JoinPoint上维护多个Advice,进行层拦截。比如Http鉴权的实现。
切入点(PointCut),就是带有通知的连接点。要切入的对象,可以是类,或方法。在Spring中,所有的方法都可以认为是JoinPoint,都可以添加Advice,但是这并不是所有都是我们真正想要的,而PointCut提供了一组规则,来匹配JointPoint,给满足规则的JointPoint添加Advice。其主要用来修饰JointPoint。
Advice的五种通知类型
前置通知(@Before):在目标方法被调用之前调用通知功能
后置通知(@After):在目标方法完成之后调用通知,此时不会关心方法的输出
返回通知(@After-Returning):在目标方法成功执行之后调用通知
异常通知(@AfterThrowing):在目标方法抛出异常后调用通知
环绕通知(@Around):通知包裹了被通知的方法,在被通知的方法调用之前和之后执行自定义的行为
做个小demo
1. 在src下新建bean包,新建Operator类
package bean; 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(* service.UserService.add()")
// public void service() {
// } @Pointcut("execution(* service.UserService.add())")
public void IService(){ } @Before("IService()")
public void doBefore(JoinPoint joinPoint) {
System.out.println(" before Advice");
} @After("IService()")
public void doAfter(JoinPoint joinPoint) {
System.out.println(" after Advice");
} @AfterReturning(pointcut = "IService()", returning = "returnVal")
public void afterReturn(JoinPoint joinPoint, Object returnVal) {
System.out.println(" after Advice return " + returnVal);
} @AfterThrowing(pointcut = "IService()", throwing = "errors")
public void afterThrowing(JoinPoint joinPoint, Throwable errors) {
System.out.println("afterThrowing Advice ..." + errors);
System.out.println(" afterThrowing..");
} @Around("IService()")
public void doAround(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println(" around Advice before"); try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println(" around Advice before");
}
}
2. src下新建service包,新建UserService类
package service; 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 ");
}
}
3.配置XML文件,在src下新建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"> <bean name="userService" class="service.UserService"></bean>
<bean name="operator" class="bean.Operator"></bean> <aop:config>
<aop:aspect id="operatorAspect" ref="operator">
<aop:pointcut id="servicePointCut" expression="execution(* service.UserService.add())"></aop:pointcut>
<aop:before pointcut-ref="servicePointCut" method="doBefore"></aop:before>
<aop:after pointcut-ref="servicePointCut" method="doAfter"></aop:after>
<aop:around pointcut-ref="servicePointCut" method="doAround"></aop:around>
<aop:after-returning pointcut-ref="servicePointCut" method="afterReturn"
returning="returnVal"></aop:after-returning>
<aop:after-throwing pointcut-ref="servicePointCut" method="afterThrowing"
throwing="errors"></aop:after-throwing>
</aop:aspect>
</aop:config>
</beans>
4.测试AOP,在src下新建test.java
import bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService; public class test {
@Test
public void demo() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService", UserService.class);
userService.add();
} }
5.运行结果
Spring学习手札(二)面向切面编程AOP的更多相关文章
- Spring学习笔记:面向切面编程AOP(Aspect Oriented Programming)
一.面向切面编程AOP 目标:让我们可以“专心做事”,避免繁杂重复的功能编码 原理:将复杂的需求分解出不同方面,将公共功能集中解决 *****所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现 ...
- spring学习总结二-----面向切面编程(AOP)思想
上一篇spring博客简总结了spring控制反转和依赖注入的相关思想知识点,这篇博文对spring的面向切的编程思想进行简单的梳理和总结. 一.面向切面的思想 与面向对象的纵向关系概念不同,面向切面 ...
- Spring学习总结之面向切面(AOP)
AOP术语 通知(advice):定义切面是什么以及什么时候使用 连接点(join point):应用在执行过程中能够插入切面的点 切点(pointcut):切点的定义会匹配通知所要织入的一个或多个连 ...
- Spring框架学习笔记(2)——面向切面编程AOP
介绍 概念 面向切面编程AOP与面向对象编程OOP有所不同,AOP不是对OOP的替换,而是对OOP的一种补充,AOP增强了OOP. 假设我们有几个业务代码,都调用了某个方法,按照OOP的思想,我们就会 ...
- Spring之控制反转——IoC、面向切面编程——AOP
控制反转——IoC 提出IoC的目的 为了解决对象之间的耦合度过高的问题,提出了IoC理论,用来实现对象之间的解耦. 什么是IoC IoC是Inversion of Control的缩写,译为控制 ...
- Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)
在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...
- 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制
spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...
- 【串线篇】面向切面编程AOP
面向切面编程AOP 描述:将某段代码“动态”的切入到“指定方法”的“指定位置”进行运行的一种编程方式 (其底层就是Java的动态代理)spring对其做了简化书写 场景: 1).AOP加日志保存到数据 ...
- [译]如何在ASP.NET Core中实现面向切面编程(AOP)
原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...
随机推荐
- C#后端接收form-data,创建实体类
public class Para_list //实体类 { public long ParemeterID { get; set; } public string Name { get; set; ...
- 内置装饰器二:@property
property 装饰器的作用 property 装饰器将方法包装成属性,将私有属性公有化,此属性只能被读取.相当于实现get方法的对象 class People: def __init__(self ...
- WKWebView 里 JS 和 native 通信的例子
native 端 初始化 wkwebview,设置 message handler webView = WKWebView.init() let usecc = self.webView.config ...
- AFNetworking 报3840
工作中遇到前后台交互,前端解析不了后端返回的数据格式 ,原因在于没有标准统一的请求格式 这是个坑,但是还是有办法修复 错误提示: Error Domain=NSCocoaErrorDomain Cod ...
- 在vue-cli建的vue项目中使用sass
前面已使用vue-cli新建了一个vue项目,参考 使用命令行创建一个vue项目的全部命令及结果 首先看下新建项目的页面和代码,有部分修改,可忽视,如下图: 然后我们在页面添加sass的代码 ...
- MySQL多源复制(八)
一.什么是多源复制 MySQL 5.7发布后,在复制方面有了很大的改进和提升.比如开始支持多源复制(multi-source)以及真正的支持多线程复制了.多源复制可以使用基于二进制日志的复制或者基于事 ...
- POJ 1045
#include<iostream> #include<cmath> #include<iomanip> using namespace std; int main ...
- Java Web入门学习(四)Eclipse与Maven、Tomcat整合配置 (重整版并解决问题)
Java Web学习(四)Eclipse与Maven整合配置 (重整版) 一.准备工作 1.Tomcat 8.5.15 2.Maven3.5 3.Eclipse Neon.3 Release (4.6 ...
- (转)MYSQL线程池总结(一)
MYSQL线程池总结(一) 原文:http://www.cnblogs.com/cchust/p/4510039.html 线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应 ...
- (转)MySQL 线程池内幕
原文:http://blog.jobbole.com/109695/ http://mysqllover.com/?p=826 http://blog.csdn.net/hsuxu/article/d ...