SpringAOP详解

1、spring AOP概述
1.1什么是springAOP?
AOP是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善,实际项目中我们一般将面向对象理解为一个静态过程,而现象切面包含一个一个动态过程,是属于在对象运行时动态织入一些功能。
1.2AOP一般是帮助 我们解决哪类问题?
实际项目中我们一般会将系统分为两大部分:核心关注点 和非核心关注点。
编程过程中首先要完成的就是核心关注点,也就是我们业务的核心。
而一些非核心关注点我们应该如何切入到系统中?两种方式:一种是硬编码,这种是违背了OCP的,另一种就是我们推荐使用的AOP、
1.3AOP在项目中的应用场景
AOP通常用户处理日志信息,事务管理,权限处理,缓存处理。
AOP在项目中的定位属于 在控制层和业务层直接用于获取业务层的信息,抓取业务层的数据,对业务层进行处理。
1.4AOP底层原理分析
1)如果使用AOP处理的业务层实现了一个接口,那么底层默认使用jdk动态代理的机制为目标实现类创建一个代理对象(则生成的代理对象同样实现了该接口、)
2)假如目标对象(被代理对象)没有实现接口,则底层默认采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型)
1.5AOP的相关术语
切面(aspect):横切面对象,一般为一个具体类的对象,借助@Aspect声明。
连接点(joinpoint):程序执行过程中某个特定的点、一般指被拦截到的方法。
切入点(pointcut):对连接点拦截内容的一种定义、一般认为多个连接点的集合。
通知(Advice):在切面的某个特定连接点上执行的动作(指对选定的方法在什么时候进行操作)
这里听着不是那么明白,后面会详细介绍。
2.1AOP的编程步骤
1)新建maven project
2)在 pom文件添加aop依赖
3)配置aop核心
4)定义核心业务(核心关注点)
5)基于特定的核心业务去定义非核心关注点、
6)配置实现非核心业务
2.2AOP基于xml实现(日志管理)
2.2.1添加依赖

<dependency>
		  <groupId>org.springframework</groupId>
		  <artifactId>spring-context</artifactId>
		  <version>4.3.9.RELEASE</version>
	    </dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.8.9</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.9</version>
		</dependency>
2.2.2创建接口
	

public interface HelloService {
			 void sayHello(String msg);
		}
2.2.3创建 实现类


public class HelloServiceImpl implements HelloService {
		public void sayHello(String msg) {
			System.out.println(msg);
		}
	}
2.2.4日志处理类(将此日志处理类定义为横切面,通过此横切面实现扩展业务)


public class LogAspect {
		public void beforeMethod(){
			System.out.println("LogAspect.beforeMethod()");
		}
		public void afterMethod(){
			System.out.println("LogAspect.afterMethod()");
		}
	}
2.2.5配置bean
<?xml version="1.0" encoding="UTF-8"?>
<beans 
default-lazy-init="true"
xmlns="http://www.springframework.org/schema/beans" 
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="  
   http://www.springframework.org/schema/beans   
   http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
   http://www.springframework.org/schema/mvc   
   http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd   
   http://www.springframework.org/schema/tx   
   http://www.springframework.org/schema/tx/spring-tx-4.3.xsd   
   http://www.springframework.org/schema/aop 
   http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
   http://www.springframework.org/schema/util 
   http://www.springframework.org/schema/util/spring-util-4.3.xsd
   http://www.springframework.org/schema/data/jpa 
   http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-4.3.xsd"> 

	    <!-- 核心业务对象 -->
	    <bean id="helloService"
	          class="spring.beans.HelloServiceImpl"/>
	<!-- 配置非核心业务对象(日志处理对象):切面 -->
	<bean id="log" 
	          class="spring.aop.LogAspect"/>
	    <!-- AOP配置(切入点,切面) -->  
	    <aop:config>
	       <!-- 配置切入点(bean,@annotation,within) -->
	       <aop:pointcut 
	            expression="within(spring.beans.HelloServiceImpl)" 
	            id="logPointCut"/>
	       <!-- 配置日志处理 -->
	       <aop:aspect ref="log" >
	           <aop:before method="beforeMethod" 
	                       pointcut-ref="logPointCut"/>
	           <aop:after  method="afterMethod"
	                       pointcut-ref="logPointCut"/>
	       </aop:aspect>
	    </aop:config>
	</beans>

最后编写测试方法进行测试

3.3.Spring AOP 编程增强

Spring中通过切入点表达式定义具体切入点,其常用AOP切入点表达式定义及说明:

指示符	作用
  1. bean 用于匹配指定bean id的的方法执行
  2. within 用于匹配指定包名下类型内的方法执行
  3. @annotation 用于匹配指定注解修饰的方法执行
    execution 用于进行细粒度方法匹配执行具体业务

bean应用于类级别,实现粗粒度的控制:
bean(“userServiceImpl”)) 指定一个类
bean("*ServiceImpl") 指定所有的后缀为service的类

within应用于类级别,实现粗粒度的切面表达式定义:
within(“aop.service.UserServiceImpl”) 指定类,只能指定一个类
within(“aop.service.") 只包括当前目录下的类
within("aop.service…
”) 指定当前目录包含所有子目录中的类

execution方法级别,细粒度的控制:
语法:execution(返回值类型 包名.类名.方法名(参数列表))
execution(void aop.service.UserServiceImpl.addUser()) 匹配方法
execution(void aop.service.PersonServiceImpl.addUser(String)) 方法参数必须为字符串
execution(* aop.service….(…)) 万能配置

@annotaion应用于方法级别,实现细粒度的控制:

@annotation(“com.jt.common.anno.RequestLog”)) 指定一个需要实现增强功能的方法

在AOP编程中有五种类型的通知:
1)前置通知 (@Before) 方法执行之前执行
2)返回通知 (@AfterReturning) 方法return之后执行
3)异常通知 (@AfterThrowing) 方法出现异常之后执行
4)后置通知 (@After) : 又称之为最终通知(finally)
5)环绕通知 (@Around) :重点掌握
执行顺序我们可以通俗的认为
其结构如下:

Try{
   @Before
   核心业务
   @AfterReturning
}catch(Exception e){
   ….
   @AfterThrowing
}finally{
   ….
   @After
}

这么写大家肯定都已经知道执行顺序了,如果是初学者,不知道这段代码 的执行顺序的话,不妨去写一个小demo测试一下

切入点及前置通知,后置通知,返回通知,异常通知,环绕通知的配置

<aop:config>
		<aop:pointcut id="pc"expression="execution(* 
com.company.spring.service..*.*(..))" >
		<aop:aspect ref="loggingAspect">
			<aop:before method="beforeMethod" pointcut-ref="pc"/>
			<aop:after method="afterMethod" pointcut-ref="pc"/>
			<aop:after-returning method="returnMethod"
 pointcut-ref="pc"/>
			<aop:after-throwing method="throwMethod" 
pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>

切入点及环绕通知的配置

<aop:config>
		<aop:pointcut id="pc"expression="execution(* 
com.company.spring.service..*.*(..))" >
		<aop:aspect ref="loggingAspect">
			<aop:around method="aroundMethod" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>

3.2.2.注解方式通知配置增强
切入点及前置通知,后置通知,返回通知,异常通知,环绕通知的配置

@Aspect
@Service
public class LogAspect {
       @Pointcut("bean(orderServiceImpl)")
	   public void doLog(){}
		   
	   @Before("doLog()")	//orderServiceImpl类中的具体方法 
	   public void doBefore(){
		   System.out.println("log before");
	   }
	   @After("doLog()")	//orderServiceImpl类中的具体方法 
	   public void doAfter(){
		   System.out.println("log after");
	   }
	   @AfterReturning("doLog()")
	   public void doAfterReturning(){
		   System.out.println("log doAfterReturning");
	   }
	   Throwing*/
	   @AfterThrowing("doLog()")
	   public void doAfterThrowing(){
		   System.out.println("log doAfterThrowing");
	   }
}

切入点及环绕通知的配置

@Component
@Aspect
public class TxManager {
	@Pointcut("execution(com.company.spring.service..*.*(..))")
	public void pointCut() {}
	@Around("pointCut()")
	public Object around(ProceedingJoinPoint joinPoint) 
			throws Throwable{
            try{
			System.out.println("事务开始");
			Object result = joinPoint.proceed();//执行目标方法
			System.out.println("提交事务");
return result;
}catch(Exception e){
System.out.println("回滚事务");
throw e;
}finally{
System.out.println("释放资源");
}
				}
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值