spring(五)(Advisor与AspectJ)

Advisor与AspectJ

1.  Advisor(顾问)

1.1 AOP一些专业术语

* 切面(Aspect) : 横切关注点。就是交叉在各个业务逻辑中的系统服务(被模块化),类似于安全验证、事务处理、日志记录都可以理解为切面。

 

* 织入(weaving) : 就是将切面代码插入到目标对象某个方法的过程,相当于我们在jdk动态代理里面的 invocationHandler接口方法的内容 。

 

* 连接点(JointPoint) :  理论上可能被切面织入的所有方法 ,比如addUser(), searchUser()的方法前、方法后或抛异常后等等。通常所有方法都可以被称为连接点。

 

* 切入点(PointCut) : 就是实际上被切面织入的方法。

 

* 目标对象(target) : 就是切入点和连接点所属的类 UserDaoImpl,被通知的对象。

 

* 通知(Advice) : 就是切面的实现,切面必须要完成的工作。

 

* 代理(Proxy) : 向目标对象应用通知之后创建的对象。

 

* 顾问(Advisor) : 其实就是通知的一个封装和延伸,可以将通知以更为复杂的方式织入到某些方法中

将切面织入到目标对象的连接点方法,使连接点成为切入点

1.2 案例讲解

1) 导入jar包

       导入 aop联盟的规范 : com.springsource.org.aopalliance-1.0.jar

       导入 spring aop实现 : spring-aop-4.2.9.RELEASE.jar

2) 编写被代理 接口和实现类

       UserDao.java

       UserDaoImpl.java

3) 编写各种通知(前置通知,后置通知,环绕通知,异常通知)

4) 为目标对象创建 , 配置applicationContext.xml

       使用ProxyFactoryBean 为目标对象创建代理

5) 测试各种通知

注意事项:

在编程时,应该使用 ProxyFactoryBean 创建代理对象(UserDAOProxy ), 不要引入原来Bean (UserDAO)。

小结:

一个代理对象只能代理一个bean,意味着在实际应用中要定义多个代理(通过默认advisor自动代理生成器来解决。

从容器中获取对象是通过代理的bean的id,而不是我们在容器里面定义的目标对象的id(通过默认advisor自动代理生成器来解决)。

通知只能切入到目标类的所有方法,不能指定某些方法(通过顾问对通知的封装实现)。

 

1.3 spring的切面 advisor

顾问(Advisor) : 他将通知进行了包装,根据通知的不同类型,在不同的时间点,将切面织入到指定的目标对象的某些连接点(方法)。


PointCutAdvisor是顾问的一种,它是一个接口,有两个实现:

* NameMatchMethodPointCutAdvisor   名称匹配方法 切入点顾问

<!-- 定义一个名称匹配切入点的顾问 -->
	<bean id="beforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice" ref="beforeAdvice"></property>
		<!-- 配置单个业务逻辑方法 -->
		<!-- <property name="mappedName" value="addUser"></property> -->
		<!-- 配置多个业务逻辑方法 -->
		<!-- <property name="mappedNames" value="addUser,searchUser"></property> -->
		<!-- 用数组的方式配置多个业务逻辑方法 -->
		<property name="mappedNames">
			<array>
				<value>addUser</value>
				<value>searchUser</value>
			</array>
		</property>
	</bean>

* RegexpMethodPointCutAdvisor  正则表达式方法匹配切入点顾问

a: * 匹配前面的子表达式任意次 比如: ao* 能匹配 a ao aoo aoooooo

b: + 匹配前面的子表达式一次或者多次   比如: ao+ 能匹配 ao aoo aooo

c: . 匹配任意字符  除"\r\n"之外的

.*  代表任意的一个字符串  .*add.* 代表包含add字符的任意字符串

<!-- 定义一个正则表达式匹配 切入点顾问  -->
	<bean id="afterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice" ref="afterAdvice"></property>
		<!-- 正则表达式的匹配  匹配单个 -->
		<!-- <property name="pattern" value=".*add.*"></property> -->
		<!-- 正则表达式的匹配  匹配多个 -->
		<!-- <property name="patterns" value=".*add.*,.*search.*"></property> -->
		<!-- 用数组的方式配置多个业务逻辑方法 -->
		<property name="patterns">
			<array>
				<value>.*add.*</value>
				<value>.*search.*</value>
			</array>
		</property>
	</bean>

Spring提供了自动代理生成器来解决要定义多个代理的问题 ,有如下两种方式:

DefaultAdvisorAutoProxyCreator  可代理所有Bean自动代理生成器

* 默认advisor自动代理生成器 (为配置文件里面所有的advisor自动生成代理)

<!-- 为配置文件中所有的advisor默认生成代理,默认代理配置文件中所有bean -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

注意:1 :为配置文件里面所有的advisor自动生成代理 /会代理配置文件里面所有注册的目标对象

BeanNameAutoProxyCreator  可选择某些切面自动代理生成器

* bean名称自动代理生成器

<!-- Bean名称自动代理生成器, -->
	<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<property name="beanNames" value="userDao"></property>
		<property name="interceptorNames" value="beforeAdvisor"></property>
	</bean>

1.4 总结

以上各种技术的运用 ,无非就是为了一个目标 : 

将我们编写的切面的实现(通知/顾问)织入到某些类的某些方法当中。

可以对你选择的目标对象织入你选择的通知/顾问(系统功能的实现)。

2.  使用AspectJ 实现AOP

对于AOP的这种编程思想 ,有很多框架或者组件进行了实现,spring实现AOP就是其中的一种,AspectJ也实现了AOP,而且实现方式更为简单,使用起来更为方便,所以spring将AspectJ对于AOP的实现引入了自己的框架当中。

2.1 AspectJ是什么

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

Spring2.0之后 为了简化 AOP编程,支持AspectJ 技术

@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面。

新版本Spring框架,建议使用AspectJ方式来开发AOP ,而不需要使用传统 Spring AOP 编程。

@Aspect定义切面

2.2 AspectJ的通知类型

@Before 前置通知,相当于BeforeAdvice

@AfterReturning 后置通知,相当于AfterReturningAdvice

@Around 环绕通知,相当于MethodInterceptor

@AfterThrowing抛出通知,相当于ThrowAdvice

@After 最终final通知,不管是否异常,该通知都会执行无论程序是否正常执行,最终通知的代码会得到执行 类似于 try{}cathc{}finally{}

2.3 切点表达式定义

标识切面织入到哪些类的那些方法当中,通过execution函数,可以定义切点的方法切入。

语法: execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

2.3.1 特殊符号

a:  * 代表0到多个任意字符

b:  .. 放在方法参数中 ,代表任意个参数 ,放在包名后面表示当前包及其所有子包路径

c:  + 放在类名后,表示当前类及其子类,放在接口后,表示当前接口及其实现类

2.3.2 举例说明

a:execution(public * *(..))   表示任意的public方法

b:execution(* set*(..))            表示任意包含以set字符开头的方法

c:execution(* com.tz.spring.dao.impl.*.*(..)) 表示com.tz.spring.dao.impl的任意类的任意方法

d:execution(* com.tz.spring.dao..*.*(..))

表示com.tz.spring.dao包下面的所有方法以及所有子包下面的所有方法

e:execution(* com.tz.spring.dao.UserDao+.*(..))            

      

f:execution(* add(String,int))  带包任意返回类型的add方法 有两个参数,类型分别为String,int

2.4 AspectJ+Spring的环境搭建

1) 下载 导入 aspectJ 开发包 (AspectJ 依赖 AOP 的 jar包 )

AspectJ开发包 :

导入spring 整合 aspectj 的jar包:

Aop联盟的包:

2)  引入aop的约束


2.4.1 基于XML配置

* 编写切面类

* 在切面类里面定义各种通知的实现方法

* 在配置文件里面对aop进行配置 :

<!-- AspectJ的aop配置 -->
	<aop:config>
		<!-- 这里是配置业务逻辑的方法 -->
		<!-- * add*(..) : 第一个*:表示包路径, 空格, add* :表示方法名称的正则表达式匹配, (..) : 表示方法的参数 -->
		<aop:pointcut expression="execution(* add*(..))" id="beforePointCut"/>
		<aop:pointcut expression="execution(* update*(..))" id="afterPointCut"/>
		<aop:pointcut expression="execution(* get*(..))" id="aroundPointCut"/>
		<aop:pointcut expression="execution(* delete*(..))" id="throwingPointCut"/>
		<aop:pointcut expression="execution(* delete*(..))" id="lastPointCut"/>
		
		<!-- 这里是配置切面的通知/顾问 的方法 -->
		<aop:aspect ref="myAspect">
			<aop:before method="beforeAdvice" pointcut-ref="beforePointCut"/>
			
			<aop:after-returning method="afterAdvice(java.lang.Object)" 
			pointcut-ref="afterPointCut" returning="result"/>
			
			<aop:around method="aroundAdvice" pointcut-ref="aroundPointCut"/>
			
			<aop:after-throwing method="afterThrowingAdvice(java.lang.Exception)" 
			pointcut-ref="throwingPointCut" throwing="ex"/>
			
			<aop:after method="lastAdvice" pointcut-ref="lastPointCut"/>
		</aop:aspect>
	</aop:config>

2.4.2 基于注解配置

* 编写切面类,加上@Aspect注解

* 实现各种通知,在实现通知的方法上加上通知的注解以及切入点表达式的注解

* 在配置文件注册切面,且加上aspectJ的自动代理


 

3.  面试题:

advisor 和 aspect 区别 ?

advisor 是 spring 中 aop定义切面,通常由一个切点和一个通知组成(是通知的封装及延伸)

aspect 是AOP联盟规范中切面 , 允许由多个切点和多个通知组成。

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值