spring框架-AOP

一、AOP
面向切面编程,对于程序内部进行横切关注,把公共的代码抽取出来,形成切面,再通过连接点去监听指定方法的执行情况,在方法执行过程中把切面织入到被监听的方法中去。方法被动的被执行某些功能代码。

二、相关概念:
Aspect(切面):
指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象.

joinpoint(连接点):
所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

Pointcut(切入点):
所谓切入点是指我们要对那些joinpoint进行拦截的定义.

Advice(通知):
所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Target(目标对象):
代理的目标对象

Weave(织入):
指将aspects应用到target对象并导致proxy对象创建的过程称为织入.

Introduction(引入):
在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

三、AOP运用
1.添加相关的jar包
aopalliance-1.0.0.jar
aspectjweaver-1.6.8.jar
commons-logging-1.1.1.jar
spring-aop-4.3.10.RELEASE.jar
spring-aspects-4.3.10.RELEASE.jar
spring-beans-4.3.10.RELEASE.jar
spring-context-4.3.10.RELEASE.jar
spring-core-4.3.10.RELEASE.jar
spring-expression-4.3.10.RELEASE.jar

2.把方法的公共抽取出来形成切面类及通知

@Component  //扫描到IOC容器中去
@Aspect  //表示这个类是一个切面类
public class LogInfo {
	/* execution(public springAOP0305.Calc.*(int, int))切面表达式,指定要监听的方法
	 *  springAOP0305.Calc.* 是一个通配符,任何方法都行,int,int是方法的参数,必须是两个int型才监听。
	 *  可以改成.. 表示任意类型,任意数量的参数都行
	 */
	//前置通知,在监听的方法执行前执行.. 
	@Before("execution(* springAOP0305.*.*(..))")
	public void before() {
		System.out.println("方法开始执行.......... ");
	}
	
	//后置通知,在方法正确执行完毕,返回结果之前执行。
	@After("execution(* springAOP0305.*.*(..))")
	public void after() {
		System.out.println("方法执行结束...");
	}
}

3.添加配置文件的配置,扫描切面类及其他的类到IOC容器中

xmlns:aop="http://www.springframework.org/schema/aop" 
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 
">
  <!-- 启用注解配置,-->
  <context:annotation-config/>
  <!-- 扫描包中的类,把有注解的类自动创建出对象,存储在IOC容器中  -->
  <context:component-scan base-package="springAOP0305"/>
  <!-- 启动AOP的代理 -->
  <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

4.调用被监听的方法

public static void main(String[] args) {
		 ApplicationContext cxt = new ClassPathXmlApplicationContext("config/applicationcontext.xml");
		 Calc c = cxt.getBean(Calc.class);
		 int result = c.add(100, 50, 20);
		 System.out.println("计算结果是:"+result);
	}

5.结果

通知:

/*
	 * execution(public springAOP0305.Calc.*(int, int))切面表达式,指定要监听的方法
	 * springAOP0305.Calc.* 是一个通配符,任何方法都行,int,int是方法的参数,必须是两个int型才监听。 可以改成..
	 * 表示任意类型,任意数量的参数都行
	 */
	// 前置通知,在监听的方法执行前执行..
	@Before("execution(* springAOP0305.*.*(..))")
	public void before(JoinPoint jp) {
		// JoinPoint 是一个连接点对象,封装了方法名称及参数,jp.getSignature().getName()方法名称
		String name = jp.getSignature().getName();
		Object[] args = jp.getArgs(); // 取连接点的参数列表
		System.out.println(name + "方法: 开始执行,参数是:" + Arrays.toString(args));
	}

	// 后置通知,在方法正确执行完毕,返回结果之前执行,不能获取方法的返回结果。
	@After("execution(* springAOP0305.*.*(..))")
	public void after(JoinPoint jp) {
		// JoinPoint 是一个连接点对象,封装了方法名称及参数,jp.getSignature().getName()方法名称
		String name = jp.getSignature().getName();
		Object[] args = jp.getArgs(); // 取连接点的参数列表
		System.out.println(name + "方法: 执行结束了,参数是:" + Arrays.toString(args));
	}

	/*
	 * 返回通知,也叫最终通知,在方法返回结果时执行,此时可以获取到方法返回的结果
	 * value表示切面表达式,
	 * returning:表示方法返回的结果封装的参数名称
	 */
	@AfterReturning(value = "execution(* springAOP0305.*.*(..))", returning = "result")
	public void afterReturn(JoinPoint jp, Object result) {
		// JoinPoint 是一个连接点对象,封装了方法名称及参数,jp.getSignature().getName()方法名称
		String name = jp.getSignature().getName();
		Object[] args = jp.getArgs(); // 取连接点的参数列表
		System.out.println(name + "方法: 正确返回结果,参数是:" + Arrays.toString(args)+",计算结果是:"+result);
	}
	//异常通知,也叫例外通知,在方法执行中出现异常才执行,否则不执行,如果有异常,则返回通知不会执行
	@AfterThrowing("execution(* springAOP0305.*.*(..))")
	public void afterThrow() {
		System.out.println("发生错误..");
	}

当有多个切面的时候,可以给切面执行顺序进行设置,在切面类前添加注解
@Order(value=1), 值越小,优先级越高。

@Aspect
@Component
@Order(value=1)  //顺序设置,值小的优先级高
public class TimeInfo {
	@Before("execution(* springAOP0305.*.*(..))")
	public void befor() {
		System.out.println("时间开始记录..");
	}
}

五、XML配置
在开发中大部分还是采用注解的方式来进行配置,事务管理机制,采用的就是注解配置,简单。

<!-- 切面类的对象 -->
  <bean id="logInfo" class="springAOP0305.LogInfo"/>
  <bean id="timeInfo" class="springAOP0305.TimeInfo"/>
  
  <!-- AOP配置 -->
  <aop:config>
    <!-- 切入点:切点表达式, -->
    <aop:pointcut expression="execution(* springAOP0305.*.*(..))" id="pcut"/>
    <!-- 切面及通知的配置 order:切面织入的顺序 -->
    <aop:aspect ref="timeInfo" order="1">
      <aop:before method="befor" pointcut-ref="pcut"/>
    </aop:aspect>
    <aop:aspect ref="logInfo" order="2">
      <aop:before method="before" pointcut-ref="pcut"/>
      <aop:after method="after" pointcut-ref="pcut"/>
    </aop:aspect>
  </aop:config>

六、通配符:
expression-匹配方法执行的连接点,是Spring最主要的切入点

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

除了返回类型模式(),名字模式和参数模式以外,其余的都是可选的,*为任意通配符

expression=“execution(* cn.itcast.service..*.*(..))”

表示作用在cn.itcast.service包及子包下所有的类的所有方法上

expression=“execution(* cn.itcast.service..*.*(java.lang.String,..))”

表示作用在cn.itcast.service包及子包下所有的类的第一个参数为String类型的方法上

expression=“execution(java.lang.String cn.itcast.service..*.*(..))”

表示作用在cn.itcast.service包及子包下所有的类的返回值类型为String的方法上

expression=“execution(!java.lang.String cn.itcast.service..*.*(..))” 

表示作用在cn.itcast.service包及子包下所有的类的返回值类型不是String的所有方法上

expression=“execution(* set**(..))” 

表示作用在任意以set开始的方法上

within-限定匹配特定类型的连接点

expression=“winthin(cn.itcast.*)”

表示作用在cn.itcast包及子包下的所有连接点

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值