栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SSM-Spring Aop

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SSM-Spring Aop

SSM学习第三天–Spring Aop

文章目录

SSM学习第三天--Spring AopSpring Aop一、Aop二、Aop术语三、AspectJ开发

1)基于XML的声明式AspectJ2)基于注解的声明式AspectJ


Spring Aop 一、Aop

Aop(Aspect Oriented Programming):面向切面编程
利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

二、Aop术语

来自https://blog.csdn.net/qq_41981107/article/details/87920537

连接点(Joinpoint) 程序执行的某个特定位置,如某个方法调用前,调用后,方法抛出异常后,这些代码中的特定点称为连接点。简单来说,就是在哪加入你的逻辑增强
连接点表示具体要拦截的方法,上面切点是定义一个范围,而连接点是具体到某个方法
切点(PointCut) 每个程序的连接点有多个,如何定位到某个感兴趣的连接点,就需要通过切点来定位。比如,连接点–数据库的记录,切点–查询条件
切点用于来限定Spring-AOP启动的范围,通常我们采用表达式的方式来设置,所以关键词是范围
增强(Advice) 增强是织入到目标类连接点上的一段程序代码。在Spring中,像BeforeAdvice等还带有方位信息
通知是直译过来的结果,我个人感觉叫做“业务增强”更合适 对照代码就是拦截器定义的相关方法,通知分为如下几种:
前置通知(before) 在执行业务代码前做些操作,比如获取连接对象
后置通知(after) 在执行业务代码后做些操作,无论是否发生异常,它都会执行,比如关闭连接对象
异常通知(afterThrowing) 在执行业务代码后出现异常,需要做的操作,比如回滚事务
返回通知(afterReturning) 在执行业务代码后无异常,会执行的操作
环绕通知(around) 这个目前跟我们谈论的事务没有对应的操作,所以暂时不谈
目标对象(Target) 需要被加强的业务对象
织入(Weaving) 织入就是将增强添加到对目标类具体连接点上的过程。
织入是一个形象的说法,具体来说,就是生成代理对象并将切面内容融入到业务流程的过程。
代理类(Proxy) 一个类被AOP织入增强后,就产生了一个代理类。
切面(Aspect) 切面由切点和增强组成,它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是将切面所定义的横切逻辑织入到切面所制定的连接点中。
比如上文讨论的数据库事务,这个数据库事务代码贯穿了我们的整个代码,我们就可以这个叫做切面。 SpringAOP将切面定义的内容织入到我们的代码中,从而实现前后的控制逻辑。 比如我们常写的拦截器Interceptor,这就是一个切面类


三、AspectJ开发

AspectJ是一种基于Java语言的AOP框架,提供强大的AOP功能。使用AspectJ实现AOP有两种方式:

1)基于XML的声明式AspectJ

通过XML文件来定义切面、切入点、通知。所有定义都是在元素内,其子元素包括、和

常用配置代码(示例):


	
	
	
		
		
			
			
			
				
				
				 
				 
				
				
				
				
				
				
		
	

具体步骤:
1、配置切面
元素包含两个属性:id(用来定义该切面的唯一标识名称)、ref(用于引用普通的Spring Bean如上述代码中的myAspect)
2、配置切入点
通过元素来定义,当元素作为元素的子元素时,表示该切入点是全局切入点,可多个切面公用。当作为的子元素,则为当前切面有效。
包含两个属性:id(用来定义该切入点的唯一标识名称)、expression(用于指定切入点关联的切入点表达式)
表示匹配com.ssm.aspectj包中任意类的任意方法的执行。
expression表达式主体;
第1个*表示返回类型、使用*代表所有类型;com.ssm.aspectj表需要拦截的包名;
后第2个*表类名,使用*表所有的类;
第3个*表方法名,使用*表所有方法;
后面()表方法的参数,中的..表任意参数
注意第一个*与包名之间有空格

3、配置通知
通知的常用属性及其描述

演示代码
(1)创建一个名为chapter03的动态Web项目;
在导入jar包时要在基础包中加入

(2)在chapter03项目的src目录下,创建一个com.ssm.aspectj包,在包里创建UserDao类,创建两个方法;

package com.ssm.aspectj;
public interface UserDao {
	public void insert();
	public void delete();
}

(3)在 com.ssm.aspectj包中,创建 UserDao接口的实现类 UserDaolmpl;

package com.ssm.aspectj;

import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao{

	public void insert() {
		//int i=10/0;
		System.out.println("添加用户");
		
	}

	public void delete() {
		System.out.println("删除用户");
		
	}

}

(4)在chapter03项目的src目录下,创建一个 com. ssm.aspectj.xml包,包中创建切面类MyAspect;

package com.ssm.aspectj.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;


public class MyAspect {
	
	//前置通知
	public void myBefore(JoinPoint joinPoint){
		System.out.print("前置通知:模拟执行权限检查");
		System.out.print("目标类为:"+joinPoint.getTarget());
		System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
	}
	//后置通知
	public void myReturning(JoinPoint joinPoint){
		System.out.print("后置通知:模拟记录日志");
		System.out.println("被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
	}
	//环绕通知
	public Object myAround(ProceedingJoinPoint point)throws Throwable{
		System.out.println("环绕开始:执行目标方法,模拟开启事务");
		Object obj=point.proceed();
		System.out.println("环绕结束,执行目标方法之后,模拟关闭事务");
		return obj;	
	}
	//异常通知
	public void myAfterThrowing(JoinPoint joinPoint,Throwable throwable){
		System.out.println("异常通知,错误了"+throwable.getMessage());
	}
	//最终通知
	public void myAfter(){
		System.out.println("最终通知,模拟方法结束后释放资源");
	}
		
}

(5)在 com. ssm.aspectj.xml包中,创建配置文件applicationContext. Xml;



	
	
	
	
	
	
		
		
			
			
			
				
				
				 
				 
				
				
				
				
				
				
		
	

(6)在com. ssm.aspectj. xm包下,创建测试类TestXmlAspect。

package com.ssm.aspectj.xml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ssm.aspectj.UserDao;

public class TextXmlAspect {

	public static void main(String[] args) {
		String xmlPath="com/ssm/aspectj/xml/applicationContext.xml";
		ApplicationContext app=new ClassPathXmlApplicationContext(xmlPath);
		UserDao userDao=(UserDao)app.getBean("userDao");
		userDao.insert();
		userDao.delete();
	}
}

运行结果如下:

三月 20, 2022 2:10:06 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@817b38: startup date [Sun Mar 20 14:10:06 CST 2022]; root of context hierarchy
三月 20, 2022 2:10:07 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [com/ssm/aspectj/xml/applicationContext.xml]
前置通知:模拟执行权限检查目标类为:com.ssm.aspectj.UserDaoImpl@1c072cb,被植入增强处理的目标方法为:insert
环绕开始:执行目标方法,模拟开启事务
添加用户
最终通知,模拟方法结束后释放资源
环绕结束,执行目标方法之后,模拟关闭事务
后置通知:模拟记录日志被植入增强处理的目标方法为:insert
前置通知:模拟执行权限检查目标类为:com.ssm.aspectj.UserDaoImpl@1c072cb,被植入增强处理的目标方法为:delete
环绕开始:执行目标方法,模拟开启事务
删除用户
最终通知,模拟方法结束后释放资源
环绕结束,执行目标方法之后,模拟关闭事务
后置通知:模拟记录日志被植入增强处理的目标方法为:delete

包结构:


2)基于注解的声明式AspectJ
注释名描述
@Aspect定义一个切面
@PointCut定义切入点表达式
@Before定义前置通知
@AfterReturning定义后置通知
@Around定义环绕通知
@AfterThrowing定义异常通知
@After定义最终通知

演示代码

创建 com.ssm.aspectj.annotation包新建MyAspect类进行修改

package com.ssm.aspectj.annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//定义切面类
@Aspect
//由于该类在Spring中作为组件使用,要添加@Component注解才能够生效
@Component
public class MyAspect {
		//定义切入点
		@Pointcut("execution(* com.ssm.aspectj.*.*(..))")
		//切入点方法
		public void myPointCut(){}
		//前置通知
		@Before("myPointCut()")
		public void myBefore(JoinPoint joinPoint){
			System.out.print("前置通知:模拟执行权限检查");
			System.out.print("目标类为:"+joinPoint.getTarget());
			System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
		}
		//后置通知
		@AfterReturning("myPointCut()")
		public void myReturning(JoinPoint joinPoint){
			System.out.print("后置通知:模拟记录日志");
			System.out.println("被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
		}
		//环绕通知
		@Around("myPointCut()")
		public Object myAround(ProceedingJoinPoint point)throws Throwable{
			System.out.println("环绕开始:执行目标方法,模拟开启事务");
			Object obj=point.proceed();
			System.out.println("环绕结束,执行目标方法之后,模拟关闭事务");
			return obj;	
		}
		//异常通知
		@AfterThrowing(value="myPointCut()",throwing="throwable")
		public void myAfterThrowing(JoinPoint joinPoint,Throwable throwable){
			System.out.println("异常通知,错误了"+throwable.getMessage());
		}
		//最终通知
		@After("myPointCut()")
		public void myAfter(){
			System.out.println("最终通知,模拟方法结束后释放资源");
		}

}
在com.ssm.aspectj.annotation包中创建applicationContext.xml


       
	
	
	
	

测试类TextAnnotation
package com.ssm.aspectj.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ssm.aspectj.UserDao;

public class TextAnnotation {

	public static void main(String[] args) {
		String xmlPath="com/ssm/aspectj/annotation/applicationContext.xml";
		ApplicationContext app=new ClassPathXmlApplicationContext(xmlPath);
		UserDao userDao=(UserDao)app.getBean("userDao");
		userDao.insert();
		userDao.delete();

	}

}
三月 20, 2022 2:31:50 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@817b38: startup date [Sun Mar 20 14:31:50 CST 2022]; root of context hierarchy
三月 20, 2022 2:31:50 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [com/ssm/aspectj/annotation/applicationContext.xml]
环绕开始:执行目标方法,模拟开启事务
前置通知:模拟执行权限检查目标类为:com.ssm.aspectj.UserDaoImpl@19e68d0,被植入增强处理的目标方法为:insert
添加用户
环绕结束,执行目标方法之后,模拟关闭事务
最终通知,模拟方法结束后释放资源
后置通知:模拟记录日志被植入增强处理的目标方法为:insert
环绕开始:执行目标方法,模拟开启事务
前置通知:模拟执行权限检查目标类为:com.ssm.aspectj.UserDaoImpl@19e68d0,被植入增强处理的目标方法为:delete
删除用户
环绕结束,执行目标方法之后,模拟关闭事务
最终通知,模拟方法结束后释放资源
后置通知:模拟记录日志被植入增强处理的目标方法为:delete

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/775153.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号