spring05——AspectJ开发

三、Aspectj能做什么

    clean modularization of crosscutting concerns, such as error checking and handling, synchronization, context-sensitive behavior, performance optimizations, monitoring and logging, debugging support, and multi-object protocols。

     大意是说:干净的模块化横切关注点(也就是说单纯,基本上无侵入),如错误检查和处理,同步,上下文敏感的行为,性能优化,监控和记录,调试支持,多目标的协议。

四、还有那些常用的Aop,以及他们的区别

Jboss Aop:我基本上没有用过,所以没有发言权
Spring Aop:Spring自己原生的Aop,只能用一个词来形容:难用。 你需要实现大量的接口,继承大量的类,所以spring aop一度被千夫所指。这于他的无侵入,低耦合完全冲突。不过Spring对开源的优秀框架,组建向来是采用兼容,并入的态度。所以,后来的Spring 就提供了Aspectj支持,也就是我们后来所说的基于纯POJO的Aop。
   区别:Spring Aop采用的动态织入,而Aspectj是静态织入。静态织入:指在编译时期就织入,即:编译出来的class文件,字节码就已经被织入了。动态织入又分静动两种,静则指织入过程只在第一次调用时执行;动则指根据代码动态运行的中间状态来决定如何操作,每次调用Target的时候都执行。有不清楚的同学,可以自己补下基础的代理知识。

https://blog.csdn.net/qq_15037231/article/details/78749581上面是转的,原地址在这。

spring支持AspectJ的开发,所以我们是用的AspectJ是在spring容器里进行的。

AspectJ开发:通过配置文件方式

新建java项目
导包
在这里插入图片描述
ps:前两个包没有spring开头是因为这是spring买的人家的

这是我的项目结构
项目结构
首先创建一个Person类

package com.cbb.bean;

/** 
 * 类描述:一个人的类
 * 作者: 地铁与人海
 * 创建日期:2019年3月13日
 * 修改人:
 * 修改日期:
 * 修改内容:
 * 版本号: 1.0.0   
 */

public class Person {
	public void eat() {
		System.err.println("吃饭......");
	}
	public void run() {
		System.err.println("跑步......");
	}
}

我们为了实现异常通知,在Person类里加了个方法

	public String run(String name) {
		System.err.println(name+"跑步......");
		//int a = 1/0;
		return name;

再创建一个通知类,写通知的类,作为系统层次的服务(模拟日志之类的东西)
我将五种通知都写在上面了,其中环绕通知和其他的通知不一样

package com.cbb.advice;

import org.aspectj.lang.ProceedingJoinPoint;

/** 
 * 类描述:通知类,做系统服务的类
 * 作者: 地铁与人海
 * 创建日期:2019年3月13日
 * 修改人:
 * 修改日期:
 * 修改内容:
 * 版本号: 1.0.0   
 */

public class MyAdvice {
	
	public void doBefore() {
		System.err.println("前通知...");
	}
	
	public void doAfter() {
		System.err.println("后通知...");
	}
	
	public void afterR() {
		System.err.println("返回后通知...");
	}
	public void throwing() {
		System.err.println("异常通知...");

	}
	
	/** 
	 * 方法描述:环绕通知的写法
	 * @param joinPoint 连接点
	 * @throws Throwable 
	 */
	public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
		System.err.println("环绕通知开始......");
		Object obj = joinPoint.proceed();
		System.err.println("环绕通知结束......");
		return obj;
	}
}

然后我们写注解,建一个applicationContext.xml文件(名字其实一直都可以随便起)
必须要有的如图:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	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">

</beans>

我们就在<beans>标签里面进行注解开发。
首先把类配置到这里面

	<!-- 只增强一个,不用注解的方式 -->
	<!-- 待被增强的类,先放到这来 -->
	<bean id = "person" class="com.cbb.bean.Person"></bean>
	<!-- 配置一个切面 -->

我们要实现的,是在使用person类的时候,添加通知类的通知进去(也就是调用方法),我们进行配置,就是配置切面(也是一个bean)和切点。
切面是所有通知,切点是要被增强的类和方法

明确之后,我们写test类

package com.cbb.test;

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

import com.cbb.bean.Person;
import com.cbb.service.SomeService;

/** 
 * 类描述:
 * 作者: 地铁与人海
 * 创建日期:2019年3月13日
 * 修改人:
 * 修改日期:
 * 修改内容:
 * 版本号: 1.0.0   
 */

public class AOPTest {
	
	@Test
	public void test() {
		ApplicationContext app = 
				new ClassPathXmlApplicationContext("applicationContext.xml");
		Person p = app.getBean(Person.class);
		p.run("jack");
	}

}

就是new类,调用方法而已。现在不会有任何通知,因为我们还没有配置。

我们开始配置,先配置一个切面

<!-- 配置一个切面 -->
	<bean id = "myAdvice" class="com.cbb.advice.MyAdvice"></bean>

其实就是把这个类也由bean进行管理

现在正是进行aop配置
配置切面。

<!-- aop配置 -->
	<aop:config>
		<!-- 配置切面  要通过ref指向做增强的bean前面-->
		<aop:aspect ref="myAdvice">
		</aop:aspect>
	</aop:config>

在里面要配置两个东西,切点和通知

配置切点

<!--配置切点  可以放到切面里面,代表只有本切面可以使用这个切点,也可以放到切面外部,代表全局,所有的切面都可以使用这个切点
				expression:写切点表达式:写切点要使用到哪个地方去。
				起个id,别的地方就可以调用了
			 -->
			<aop:pointcut expression="execution(* com.cbb.*.*(..))" id="myCut"/>

我们将它放在切面里面

	<!-- aop配置 -->
	<aop:config>
		<!-- 配置切面  要通过ref指向做增强的bean前面-->
		<aop:aspect ref="myAdvice">
			<!--配置切点  可以放到切面里面,代表只有本切面可以使用这个切点,也可以放到切面外部,代表全局,所有的切面都可以使用这个切点
				expression:写切点表达式:写切点要使用到哪个地方去。
			 -->
			<aop:pointcut expression="execution(* com.cbb..*.*(..))" id="myCut"/>
		</aop:aspect>
	</aop:config>

然后我们进行配置通知,让myAdvice里面的各个方法声明为各种通知

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	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">
	<!-- 只增强一个,不用注解的方式 -->
	<!-- 待被增强的类,先放到这来 -->
	<bean id = "person" class="com.cbb.bean.Person"></bean>
	<!-- 配置一个切面 -->
	<bean id = "myAdvice" class="com.cbb.advice.MyAdvice"></bean>
	
	<!-- aop配置 -->
	<aop:config>
		<!-- 配置切面  要通过ref指向做增强的bean前面-->
		<aop:aspect ref="myAdvice">
			<!--配置切点  可以放到切面里面,代表只有本切面可以使用这个切点,也可以放到切面外部,代表全局,所有的切面都可以使用这个切点
				expression:写切点表达式:写切点要使用到哪个地方去。
			 -->
			<aop:pointcut expression="execution(* com.cbb..*.*(..))" id="myCut"/>
			<!-- 配置前通知     method:对应切面的哪个方法     pointcut-ref:对应得切点-->
			<aop:before method="doBefore" pointcut-ref="myCut"/>
			<aop:before method="doBefore" pointcut-ref="myCut"/><!-- 可以重复· -->
			<!-- 后通知 :可以称为最终通知,无论如何都会执行的-->
			<aop:after method="doAfter" pointcut-ref="myCut"/>
			<!-- 返回后通知 :只有正常返回才会执行-->
			<aop:after-returning method="afterR" pointcut-ref="myCut"/>
			<!-- 异常通知:只有异常抛出才会执行-->
			<aop:after-throwing method="throwing" pointcut-ref="myCut"/>
			<!-- 环绕通知: = 前通知+返回后通知 在待增强的方法执行的前后执行 -->
			<aop:around method="doAround" pointcut-ref="myCut"/>
		</aop:aspect>
	</aop:config>
</beans>

然后我们就可以实现了
实现效果

切点表达式

切点表达式的解释
在这里插入图片描述
我们通过参数的个数和类型进行区分方法,是因为会有重载方法

切点表达式功能:

  • 1.可以控制返回参数类型
  • 2.控制参数
  • 3.控制类的深度(根据控制包,来控制深度)
  • 4.面向接口的(你切的接口方法,则此接口的实现类也会被切)

符号(通配符)功能

符号功能
*在返回值上,代表任意类型。在路径上,代表任意类或者是方法
两个点(破编辑器,打不出来,自动变成三个点了,参考上面吧)任意多个。0~N个

注意点:
execution(* com.cbb. * . *(..)) 对com.cbb包下的所有类切,但是对子包下的类无效
execution(* com.cbb.. * . *(..)) 对com.cbb包下 和 子包下的所有类切
就是.和*的区别,注意。
最好使用下面那个,简洁大方,宁杀错不放过。

还有两种开发方式,我现在不讲,因为没时间了,我需要把老师最近讲的内容也整理到csdn上,有需要的童鞋可以把邮箱留下,我给把课件发过去。

END

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值