spring AOP

AOP概念

定义:面向切面编程

-----------------------------------------------------------------------------------------

理解:将共同的业务从传统业务中抽离出来,单独封装,通过配置的形式进行关联

优点:可以在不修改原有逻辑代码的情况下给系统追加功能

-----------------------------------------------------------------------------------------

AOP典型应用

1.追加事务控制

2.异常日志记录

3.测试模块性能

-----------------------------------------------------------------------------------------

案例:要求在每个Controller方法执行之前输出打桩信息

封装一个组件,通过配置将封装的组件追加到每一个Controller方法中

AOP的相关概念:切面,切入点,通知,动态代理

切面(aspect):指的是封装的共同处理的组件,并且能够切入到其他组件的方法上,可以理解为封装的部分代码

切入点(pointcut):用于指定目标组件的方法

1.方法限定表达式

  可以给某个组件中部分方法追加共同功能

  execution(修饰符?   返回类型  方法名称(参数) 异常抛出?)

  例如:execution(*   add*(..))------匹配到add开头的所有方法(在部分方法上追加)

  例如:execution(*   cn.tedu.cloud_note.UserService.*  (..))------匹配到UserService包下面的所有方法

  例如:execution(*   cn.tedu.cloud_note.service.*.*  (..))------匹配到service包下所有类的所有方法

  例如:execution(*   cn.tedu.cloud_note.service..*  (..))------匹配到service包及其子包下面的所有方法

---------------------------------------------------------------------------------------

2.类型限定表达式(重点且通用)

  可以给某个组件所有方法追加共同功能

  within(类型)

  例如:within(cn.tedu.cloud_note.service.UserService)------匹配到UserService组件下面的所有方法

  例如:within(cn.tedu.cloud_note.service.*)------匹配到service包下所有类的所有方法

  例如:within(cn.tedu.cloud_note.service..*)------匹配到service包及其子包下的所有方法

---------------------------------------------------------------------------------------

3.bean名称限定表达式

  可以给某个组件中所有方法追加共同功能

  bean(id名字)   注意id的首字母

  例如:bean(userService)------匹配id=userService组件的所有方法

  例如:bean(*Service)------匹配以Service结尾的组件的所有方法

-----------------------------------------------------------------------------------------

通知:用于指定切入的时机,spring提供了5种通知类型

try{

前置通知<aop:before>

//执行的目标方法

后置通知<aop:after-returning>

}catch{

异常通知<aop:after-throwing>//例如:日志

}finally{

最终通知<aop:after>

@around=前置+后置(环绕通知)

-----------------------------------------------------------------------------------------

代码如下:

package cn.tedu.cloud_note.aspect;

public class LoggerBean {
	public void logController(){
		System.out.println("AOP功能注入!");
	}
}

-----------------------------------------------------------------------------------------

使用配置文件配置AOP:

<!-- 配置一个bean,用于实例化切面部分的代码-->
	<bean id="loggerBean" class="cn.tedu.cloud_note.aspect.LoggerBean"></bean>
	
	<!--  -->
	<aop:config>
	  <!-- 通过ref关联组件类 -->
	  <aop:aspect ref="loggerBean">
	    <!-- 通过method指定处理方法(bean中类里面的方法) pointcut切入点-->
	    
	    <!-- 类型限定表达式(重点且通用)controller包及其子包下的所有方法 -->
	    <!-- 
	    <aop:before method="logController" pointcut="within(cn.tedu.cloud_note.controller..*)"/>
	     -->
	     
	     <!-- 使用方法限定类型 service包下的所有类中的所有方法 -->
	     <!-- 
	    <aop:before method="logController" pointcut="execution(* cn.tedu.cloud_note.service.*.*(..))"/>
	     -->
	     
	     <!-- bean(id)限定类型     因为使用的是bean的id,所以属于类级别 -->
	    <aop:before method="logController" pointcut="bean(*Controller)"/>
	  </aop:aspect>
	</aop:config>

在id后缀为Controller的组件中切入方法logController,当调用Controller组件的时候会先调用该方法,使用了前置通知(before)

-----------------------------------------------------------------------------------------

切面:要给代码追加的功能(单独封装的代码)

切入点:给谁(所有的Controller)增加功能

通知:切入的时机(前置,后置,环绕......)

-----------------------------------------------------------------------------------------

动态代理

理解:spring中IOC注入的是一个bean的实现类,而AOP原理是使用动态代理技术,动态创建一个新的类型,重写目标接口或目标类的方法,在重写方法中追加了要切入的功能代码,然后实现注入

动态生成一个新的类型:(追加的处理和原有的代码功能)

注意:事务处理的时候需要配置

示意图:

-----------------------------------------------------------------------------------------

AOP事务的配置文件:

<!-- spring的事务处理,通过AOP实现的 -->
<!-- 定义事务管理Bean -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dbcp" />
</bean>

<!-- 用于支持 @Transactional 注解 必须配置事务管理器属性, 其值是一个Bean的ID--> 
<tx:annotation-driven transaction-manager="txManager"/>

以UserServiceImpl为例:

@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {

加上@Transactional注解

-----------------------------------------------------------------------------------------

动态代理测试:

public class TestUserService {
	private UserService service;
	@Before
	public void init(){
		String[] conf = {"conf/spring-mvc.xml",
						 "conf/spring-mybatis.xml",
						 "conf/spring-transaction.xml"
						 };
		ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
		service = ac.getBean("userService",UserService.class);
	}
	
	@Test//测试:用户名不存在
	public void test1(){
		NoteResult<User> result = service.checkLogin("abc", "123456");
		//输出service是什么类型的--UserServiceImpl的一个实例
		System.out.println(service.getClass().getName());
	}
}

若不使用动态代理,则输出的是一个实现类:cn,tedu.cloud_note.service.UserServiceImpl

由于UserServiceImpl 使用了动态代理,所以注入的该实例为动态生成的额类型:com.sun.proxy.$Proxy21

=====================================================================

以上结构主要是原理,理解,重点是以下代码:利用注解配置AOP

AOP注解配置

@Component   起到定义<bean>的作用

@Aspect           起到<aop:aspect ref="loggerBean">的作用

@Before           起到<aop:before method="logController" pointcut="within()"/>的作用

-----------------------------------------------------------------------------------------

使用注解配置AOP:

spring-aop.xml文件:

<!-- 配置AOP注解扫描 --> 
<context:component-scan base-package="cn.tedu.cloud_note.aspect" />
	
<!-- 开启注解标记 -->
<aop:aspectj-autoproxy />

-----------------------------------------------------------------------------------------

package cn.tedu.cloud_note.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component  //定义bean
@Aspect     //表示切面代码
public class LoggerBean {
	
	@Before("within(cn.tedu.cloud_note.controller..*)")//切入点
	public void logController(){
		System.out.println("AOP功能注入!");
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荒--

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值