1. 自动代理:
上面这两种代理的方式不好,需要为每一个类配置一个独立的ProxyFactoryBean.(如果需要代理的类特别的多,每个类都需要创建一个代理的类.)
根据切面Advisor的定义的信息,看到哪些类的哪些方法需要增强.(为这些需要增强的类生成代理.
自动代理:基于后处理BeanPostProcessor完成代理.
代理机制不同
基于ProxyFactoryBean代理:先有被代理对象,将被代理对象传递给代理对象,为其生成代理.
自动代理:基于BeanPostProcessor代理.在生成类的过程中产生一个代理对象,返回的就是代理对象本身.
BeanNameAutoProxyCreator 根据Bean名称创建代理DefaultAdvisorAutoProxyCreator 根据Advisor本身包含信息创建代理AnnotationAwareAspectJAutoProxyCreator 基于Bean中的AspectJ 注解进行自动代理
== > BeanNameAutoProxyCreator:
<!-- 后处理Bean配置:不需要配置id --><!-- 自动代理 --><bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><!-- 配置Bean的名称 --><property name="beanNames" value="*Dao"/><property name="interceptorNames" value="beforeAdvice"/></bean>
<!-- 定义切面(带有切点切面) --><bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property name="pattern" value="cn\.itcast\.spring3\.demo4\.CustomerDao\.add.*"/><property name="advice" ref="aroundAdvice"/></bean><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
区分:
代理机制不同:
基于ProxyFactoryBean代理:先有被代理对象,将被代理对象传递给代理对象,为其生成代理.自动代理:基于BeanPostProcessor代理.在生成类的过程中产生一个代理对象,返回的就是代理对象本身.
2. 基于AspectJ的AOP的开发
:
2.1 什么是AspectJ
AspectJ概述
Spring为了简化AOP的开发,引入AspectJ技术.
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
Spring2.0以后新增了对AspectJ切点表达式支持
AspectJ的通知类型;
@Before 前置通知,相当于BeforeAdvice@AfterReturning 后置通知,相当于AfterReturningAdvice@Around 环绕通知,相当于MethodInterceptor@AfterThrowing抛出通知,相当于ThrowAdvice@After 最终final通知,不管是否异常,该通知都会执行@DeclareParents 引介通知,相当于IntroductionInterceptor (不要求掌握)
AspectJ的切点的表达式定义:
配置哪些类的哪些方法需要使用增强:
* 类似于正则的方法切点切面.
语法:
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)例如:execution(* *(..));execution(* cn.itcast.spring3.demo1.UserDao.*(..))execution(* cn.itcast.spring3.demo1.*(..))execution(* cn.itcast.spring3.demo1..*(..))execution(* cn.itcast.dao.UserDAO+.*(..))
2.2基于注解AspectJ
步骤一:引入AspectJ的相应jar包:
aspectJ的开发需要依赖aop的环境.
引入aspectJ的jar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar引入spring整合aspectJ的jar包:spring-aspects-3.2.0.RELEASE.jar
步骤二:引入配置文件:
Log4j和spring的配置文件
步骤三:创建包和类:
cn.green.demo5UserDaoUserDaoImpl
步骤四:定义切面:
切面:就是切点和通知组合.
在哪些类的哪些方法上使用增强.
定义切面:
@Aspect
定义增强:
@Before 前置通知,相当于BeforeAdvice@AfterReturning 后置通知,相当于AfterReturningAdvice@Around 环绕通知,相当于MethodInterceptor@AfterThrowing抛出通知,相当于ThrowAdvice@After 最终final通知,不管是否异常,该通知都会执行@DeclareParents 引介通知,相当于IntroductionInterceptor (不要求掌握)
代码:
package cn.green.demo5;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;@Aspectpublic class MyAspectAnno {@Before(value="execution(* cn.green.demo5.UserDao.add(..))")public void before(){System.out.println("这是before增强.....");}}
步骤五:配置:
引入aop的约束
<?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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 基于AspectJ的自动代理.使用AnnotationAwareAspectJAutoProxyCreator --><aop:aspectj-autoproxy /><bean id="userDao" class="cn.green.demo5.UserDaoImpl"></bean><bean id="myAspectionAnno" class="cn.green.demo5.MyAspectAnno"></bean></beans>
测试样例:
package cn.green.demo5;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext3.xml")public class TestCase{@Resource(name="userDao")private UserDao userDao;@Testpublic void demo(){userDao.delete();userDao.update();userDao.add();userDao.find();}}
结果:
delete run....update run....这是before增强.....add run....find run....
2.2.1 AspectJ的通知的类型:
@Before:前置通知:在目标方法之前执行.(不能拦截目标方法.)* JoinPoint:连接点@AfterReturing:后置通知:在目标方法执行之后执行.* JoinPoint:连接点* Object:返回值// 后置增强:@AfterReturning(value="execution(* cn.itcast.spring3.demo1.UserDao.delete(..))",returning="result")public void afterReturing(JoinPoint joinPoint,Object result){System.out.println("后置增强=============="+result);}@Around:环绕通知:// 环绕通知:(阻止目标对象的方法执行)@Around(value="execution(* cn.itcast.spring3.demo1.UserDao.find(..))")public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("环绕前增强=============");Object obj = joinPoint.proceed();System.out.println("环绕后增强=============");return obj;}@AfterThrowing:抛出异常通知:// 抛出异常通知:@AfterThrowing(value="execution(* cn.itcast.spring3.demo1.UserDao.find(..))",throwing="e")public void afterThrowing(Throwable e){System.out.println("异常通知========="+e.getMessage());}@After:最终通知.类似finally代码块.// 最终通知:@After(value="execution(* cn.itcast.spring3.demo1.UserDao.find(..))")public void after(){System.out.println("最终通知===========");}
2.2.2AspectJ的切点的定义:
// 定义一个切点:@Pointcut(value="execution(* cn.itcast.spring3.demo1.UserDao.find(..))")private void mypointcut(){}
面试题:
Advisor 和 Aspect区别?Advisor:是Spring传统AOP开发中提供一个切面概念.一般情况下都一个切入点和一个通知组合.Aspect:是真正意义上的切面,可以有多个切入点和多个通知组合.
2.3 基于XML的AspectJ骤一:引入AspectJ的相应jar包:
aspectJ的开发需要依赖aop的环境.
引入aspectJ的jar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar引入spring整合aspectJ的jar包:spring-aspects-3.2.0.RELEASE.jar
步骤二:引入配置文件:
Log4j和spring的配置文件
步骤三:创建包和类:
cn.spring3.demo2OrderDao
步骤四:编写切面类:
public class MyAspectXml {public void before(){System.out.println("前置增强============");}}
步骤五:修改配置文件:
<bean id="orderDao" class="cn.spring3.demo2.OrderDao"></bean><bean id="myAspect" class="cn.spring3.demo2.MyAspectXml"></bean><!-- aop的配置 --><aop:config><!-- 定义切点 --><aop:pointcut expression="execution(* cn.spring3.demo2.OrderDao.add(..))" id="mypointcut"/><!-- 定义切面 --><aop:aspect ref="myAspect"><aop:before method="before" pointcut-ref="mypointcut"/></aop:aspect></aop:config>
步骤六:编写测试:
其他类型的通知配置;
<!-- aop的配置 --><aop:config><!-- 定义切点 --><aop:pointcut expression="execution(* cn.spring3.demo2.OrderDao.add(..))" id="mypointcut1"/><aop:pointcut expression="execution(* cn.spring3.demo2.OrderDao.delete(..))" id="mypointcut2"/><!-- 定义切面 --><aop:aspect ref="myAspect"><!-- <aop:before method="before" pointcut-ref="mypointcut1"/> --><!-- <aop:around method="around" pointcut-ref="mypointcut1"/> --><aop:after method="after" pointcut-ref="mypointcut1"/><aop:after-throwing method="afterThrowing" pointcut-ref="mypointcut1" throwing="e"/><aop:after-returning method="afterReturing" pointcut-ref="mypointcut2" returning="result"/></aop:aspect></aop:config>
本文深入探讨Spring AOP与AspectJ的自动代理机制,通过BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator与AnnotationAwareAspectJAutoProxyCreator的比较,详细阐述了基于后处理BeanPostProcessor的自动代理过程。同时,文章介绍了如何利用AspectJ进行基于注解的AOP开发,包括AspectJ通知类型、切点表达式定义、基于注解的配置与测试案例,以及如何通过XML或注解方式定义切面、通知及配置。
267

被折叠的 条评论
为什么被折叠?



