7、SpringAOP

7.1、AOP的概念

Aspect oritention programming(面向切面编程),Spring的AOP使用动态代理实现,如果一个类实现了接口,那么spring就使用JDK的动态代理完成AOP,如果一个类没有实现接口,那么spring就是用cglib完成AOP;

AOP当中的概念:

①切入点Pointcut:在哪些类,哪些方法上面切(where);

②通知/增强Advice:在方法的什么时机(when)做什么(what);

③切面Aspect:切入点+通知:什么时间,什么地点,干什么

④织入Weaving:把切面加入到对象,并创建出代理对象的过程(Spring自动搞定)

7.2、xml中配置aop

1、添加jar包

com.springsource.org.aopalliance-1.0.0.jar、com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

2、引入aop的命名空间

<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
        ">
   <context:property-placeholder location="classpath:db.properties"/>
   <context:component-scan base-package="cn.org.kingdom"/>
</beans>

3、xml配置

<aop:config>
    <!--做什么 -->
<aop:aspect ref="txManager">
    		<!--什么地点,哪些方法上-->
			<aop:pointcut expression="execution(* cn.org.kingdom.aop_xml.*ServiceImpl.*(..)) " id="txPoint"/> 
    		<!--时机:方法前、方法后、方法前后 -->
			<aop:before method="beginTransaction" pointcut-ref="txPoint"/>
		</aop:aspect>
</aop:config>

注意执行表达式的格式:

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

modifiers-pattern:修饰符

ret-type-pattern:返回值的类型

declaring-type-pattern:这个方法的类名

name-pattern:方法名

param-pattern:参数

throws-pattern:异常

语法案例:

1.任意公共方法的执行:
execution(public * *(..))
2.任何一个名字以“set”开始的方法的执行:
execution(* set*(..))
3.AccountService接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
4.在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))
5.在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service..*.*(..))

7.3、Spring中的各种通知

aop:before(前置通知):在方法执行之前执行增强操作(增强类中的指定增强方法)

<aop:before method="beginTransaction" pointcut-ref="txPoint"/> 

aop:after-returning(后置通知):在方法正常执行完成之后执行增强操作;

<aop:after-returning method="commit" pointcut-ref="txPoint"/>

异常通知:在业务方法中出现异常,需要调用的增强操作 throwing="ex":决定方法定义为:public void rollback(Throwable ex):

<aop:after-throwing method="rollback" pointcut-ref="txPoint" throwing="ex"/>

aop:after(最终通知):在方法执行之后执行,相当于在finally里面执行

<aop:after method="close" pointcut-ref="txPoint"/> 

aop:around(环绕通知):把方法的执行包裹起来,环绕通知有两个要求

​ 1、方法必须要返回一个Object(返回的结果)

​ 2、方法的第一个参数必须是ProceedingJoinPoint(可以继续向下传递的切入点)

<aop:around method="around" pointcut-ref="txPoint"/>

完整代码

//PersonService
package cn.org.kingdom.service;
public interface PersonService {
	public abstract int add(String msg);
}
//PersonServiceImpl
package cn.org.kingdom.service.impl;
import org.springframework.stereotype.Service;

import cn.org.kingdom.service.PersonService;
@Service("personService")
public class PersonServiceImpl implements PersonService {
	public int add(String msg) {
		System.out.println("执行add操作");
		System.out.println(10/0);
		return 0 ; 
	}
}
//事务管理类
package cn.org.kingdom.ts;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component("ts")
public class Transaction {
	public void begin(){
		System.out.println("开启事务");
	}
	public void commit(){
		System.out.println("提交事务");
	}
	public void rollback(Throwable ex){
		System.out.println("回滚事务");
		System.out.println("发生的异常通知是:"+ex);
	}
	public void closeConnection(){
		System.out.println("关闭连接");
	}
	public Object around(ProceedingJoinPoint pjp){
		Object value = null ; 
		try{
			begin();
			value = pjp.proceed();
			commit();
		}catch(Throwable e) {
			rollback(e);
		}finally{
			closeConnection();
		}
		return value;
	}
}

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
        ">
   <context:property-placeholder location="classpath:db.properties"/>
   <!-- 扫包 -->
   <context:component-scan base-package="cn.org.kingdom"/>
   <aop:config>
   		<aop:aspect ref="ts">
   			<aop:pointcut expression="execution(* cn.org.kingdom.service..*.*(..))" id="mypointcut"/>
   			<aop:around method="around" pointcut-ref="mypointcut"/>
   		</aop:aspect>
   </aop:config>
</beans>

7.4、aop的注解配置

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
        ">
   <context:property-placeholder location="classpath:db.properties"/>
   <!-- 扫包 -->
   <context:component-scan base-package="cn.org.kingdom"/>
   <aop:aspectj-autoproxy/>
</beans>

java配置

package cn.org.kingdom.ts;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component("ts")
@Aspect
public class Transaction {
	@Pointcut(value="execution(* cn.org.kingdom.service..*.*(..))")
	public void pointcut(){}
    //注意value为方法名,并且加括号
	@Around(value="pointcut()")
	public Object around(ProceedingJoinPoint pjp){
		Object value = null ; 
		try{
			begin();
			value = pjp.proceed();
			commit();
		}catch(Throwable e) {
			rollback(e);
		}finally{
			closeConnection();
		}
		return value;
	}
	public void begin(){
		System.out.println("开启事务");
	}
	public void commit(){
		System.out.println("提交事务");
	}
	public void rollback(Throwable ex){
		System.out.println("回滚事务");
		System.out.println("发生的异常通知是:"+ex);
	}
	public void closeConnection(){
		System.out.println("关闭连接");
	}
	
}

posted @ 2021-04-09 14:40  Mirindasky  阅读(46)  评论(0编辑  收藏  举报