Spring(七)----Spring AOP

spring提供了aop的功能,我们只要知道怎么用。

代理对象不用我们去生成了。spring帮我们生成。但是,我们得去配。

增强需要自己编写。比如,要写日志。那么写日志的代码需要自己来写。

写增强,再配置。配完了,就会帮我们去生成代理对象,帮我们做aop相关的功能。

aop有两种。一是,spring自己提供的实现。但是,spring自己的实现比较麻烦。

另一家公司,AspectJ,也提供了aop的实现。spring发现,AspectJ的aop实现比较简单。spring就把它拿过来了,作为自己的实现的方式。开发中,一般都会用AspectJ的方式。

一、aop相关术语

1. Joinpoint(连接点)

所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。一个类中的所有方法都可以称为是连接点。这些方法都是可以被增强的。spring只能对方法增强。

public class BookDaoImpl {
	public void save() {
		System.out.println("保存图书...");
	}

	public void update() {
		System.out.println("修改图书...");
	}
}

这里的两个方法都称为连接点。

2. Pointcut(切入点)

所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。

上面的代码。如果,我们只想对save()方法做增强,那么,save()方法就是切入点。当程序执行到切入点的时候,增强就来了。

3. Advice(通知/增强)

所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能
4. Introduction(引介)

 引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field

5. Target(目标对象) -- 代理的目标对象

就是我们上面代码中的BookDaoImpl类的对象。也可以叫做被增强的对象

6. Weaving(织入) -- 是指把增强应用到目标对象来创建新的代理对象的过程

7. Proxy(代理) -- 一个类被AOP织入增强后,就产生一个结果代理类

8. Aspect(切面) -- 是切入点和通知的结合,以后咱们自己来编写和配置的


二、AspectJ的XML方式完成AOP的开发

步骤一:创建JavaWEB项目,引入具体的开发的jar包
先引入Spring框架开发的基本开发包
再引入Spring框架的AOP的开发包
spring的传统AOP的开发的包

  • spring-aop-4.2.4.RELEASE.jar
  • com.springsource.org.aopalliance-1.0.0.jar  aop联盟,定义了很多规范
aspectJ的开发包
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar  --AspectJ的包
  • spring-aspects-4.2.4.RELEASE.jar --spring整合AspectJ的包

步骤二:创建Spring的配置文件,引入具体的AOP的schema约束

<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>
步骤三:创建包结构,编写具体的接口和实现类
CustomerDao -- 接口
CustomerDaoImpl -- 实现类
步骤四:将目标类配置到Spring中
<bean id="customerDao" class="com.ken.demo3.CustomerDaoImpl"/>
步骤五:定义切面类
/**
 * 切面类:切入点+通知
 *
 */
public class MyAspectXml {

	/**
	 * 通知(具体的增强)
	 */
	public void log() {
		System.out.println("记录日志...");
	}
}
步骤六:在配置文件中定义切面类
<bean id="myAspectXml" class="com.ken.demo3.MyAspectXml"/>
步骤七:在配置文件中完成aop的配置
<!-- 配置aop -->
<aop:config>
	<!-- 配置切面类:切入点+通知 -->
	<aop:aspect ref="myAspectXml">
		<!-- 配置前置通知,save方法执行之前,增强的方法会执行 -->
		<!-- 切面类里的哪个方法。myAspectXml切面的log方法(有可能有多个切面,也可能有多个方法) -->
		<!-- 切入点表达式:execution(public void com.ken.demo3.CustomerDaoImpl.save()) -->
		<aop:before method="log" pointcut="execution(public void com.ken.demo3.CustomerDaoImpl.save())" />
	</aop:aspect>
</aop:config>
步骤八:完成测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo3 {

	@Resource(name = "customerDao")
	private CustomerDao customerDao;

	@Test
	public void run1() {
		customerDao.save();
		customerDao.update();
	}
}

三、切入点的表达式

<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="customerDao" class="com.ken.demo3.CustomerDaoImpl" />
	<!-- 切面类 -->
	<bean id="myAspectXml" class="com.ken.demo3.MyAspectXml" />
	<!-- 配置aop -->
	<aop:config>
		<aop:aspect ref="myAspectXml">
			<!-- 切入点的表达式
				1.execution() 固定的,不能不写
				2.public 可以省略不写
				3.void,返回值可以出现* 表示任何类型,返回值类型不能不写
				4.包名可以使用*代替。一个*只表示一层包。简写:*..*,表示任意层包。不能不写。
				5.*DaoImpl:类名,表示以DaoImpl结尾
				6.方法:save*(),一般以save开头
				7.方法的参数:..表示任意参数
			 -->
			<!-- <aop:before method="log" pointcut="execution(public void com.ken.demo3.CustomerDaoImpl.save())" /> -->
			
			<!-- public 可以省略不写 -->
			<!-- <aop:before method="log" pointcut="execution(void com.ken.demo3.CustomerDaoImpl.save())" /> -->
			
			<!-- void,返回值可以出现* 表示任何类型,返回值类型不能不写 -->
			<!-- <aop:before method="log" pointcut="execution(* com.ken.demo3.CustomerDaoImpl.save())" /> -->
			
			<!-- 包名可以使用*代替。一个*只表示一层包。简写:*..*,表示任意层包。不能不写。 -->
			<!-- <aop:before method="log" pointcut="execution(* *..*.CustomerDaoImpl.save())" /> -->
			
			<!-- *DaoImpl:类名,表示以DaoImpl结尾 -->
			<!-- <aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save())" /> -->
			
			<!-- 方法:save*(),一般以save开头 -->
			<!-- <aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save*())" /> -->
			
			<!-- 方法的参数:..表示任意参数 -->
			<aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save*(..))" />
		</aop:aspect>
	</aop:config>
</beans>

四、AOP的通知类型

1. 前置通知
在目标类的方法执行之前执行。

配置文件信息:

<aop:config>
	<aop:aspect ref="myAspectXml">
		<aop:before method="log" pointcut="execution(* *..*.*DaoImpl.save*(..))" />
	</aop:aspect>
</aop:config>
应用:可以对方法的参数来做校验
2. 最终通知

在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。

不管程序执行成功还是失败,方法执行之后,都会通知。

在配置文件中编写具体的配置:

<aop:config>
	<aop:aspect ref="myAspectXml">
		<aop:after method="after" pointcut="execution(* *..*.*DaoImpl.save*(..))" />
	</aop:aspect>
</aop:config>
应用:例如像释放资源
3. 后置通知
方法正常执行后的通知。 只有方法执行成功之后,才会通知。

在配置文件中编写具体的配置:

<aop:config>
	<aop:aspect ref="myAspectXml">
		<aop:after-returning method="afterReturning" pointcut="execution(* *..*.*DaoImpl.save*(..))" />
	</aop:aspect>
</aop:config>
应用:可以修改方法的返回值
4. 异常抛出通知
在抛出异常后通知

在配置文件中编写具体的配置:

<aop:config>
	<aop:aspect ref="myAspectXml">
		<aop:after-throwing method="afterThrowing" pointcut="execution(* *..*.*DaoImpl.save*(..))" />
	</aop:aspect>
</aop:config>
应用:包装异常的信息
5. 环绕通知
方法的执行前后执行。配置事务很好。

在配置文件中编写具体的配置:

<aop:config>
	<aop:aspect ref="myAspectXml">
		<aop:around method="around" pointcut="execution(* *..*.*DaoImpl.save*(..))" />
	</aop:aspect>
</aop:config>
要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。

spring_aop_xml代码

五、Spring框架的AOP--注解方式

步骤一:创建JavaWEB项目,引入具体的开发的jar包
先引入Spring框架开发的基本开发包
再引入Spring框架的AOP的开发包
spring的传统AOP的开发的包
spring-aop-4.2.4.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
aspectJ的开发包
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar
步骤二:创建Spring的配置文件,引入具体的AOP的schema约束

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>  
步骤三:创建包结构,编写具体的接口和实现类
CustomerDao -- 接口
CustomerDaoImpl -- 实现类
步骤四:将目标类配置到Spring中
<bean id="customerDao" class="com.ken.demo1.CustomerDaoImpl"/>
步骤五:定义切面类
添加切面和通知的注解
@Aspect -- 定义切面类的注解
通知类型(注解的参数是切入点的表达式)
@Before -- 前置通知
@AfterReturing -- 后置通知
@Around -- 环绕通知
@After -- 最终通知
@AfterThrowing -- 异常抛出通知
具体的代码如下
@Aspect
public class MyAspectAnno {

	// @Before(value = "execution(public void com.ken.demo1.CustomerDaoImpl.save())")
	@Before(value = "MyAspectAnno.fn()")
	public void log() {
		System.out.println("记录日志...");
	}

	// @After(value = "execution(public void com.ken.demo1.CustomerDaoImpl.save())")
	@After(value = "MyAspectAnno.fn()")
	public void after() {
		System.out.println("最终通知...");
	}

	// @Around(value = "execution(public void com.ken.demo1.CustomerDaoImpl.save())")
	@Around(value = "MyAspectAnno.fn()")
	public void around(ProceedingJoinPoint joinPoint) {
		System.out.println("环绕通知1...");
		try {
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("环绕通知2...");
	}

	//配置通用的切入点。使用@Pointcut定义通用的切入点
	@Pointcut(value = "execution(public * *..*.*DaoImpl.save*(..))")
	public void fn() {

	}
}
步骤六:在配置文件中定义切面类
<bean id="myAspectAnno" class="com.ken.demo1.MyAspectAnno" />
步骤七:在配置文件中开启自动代理
<aop:aspectj-autoproxy/>
完成测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {

	@Resource(name = "customerDao")
	private CustomerDao customerDao;

	@Test
	public void run1() {
		customerDao.save();
		customerDao.update();
	}
}

spring aop注解方式代码



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值