Spring的AOP自动代理(含AspectJ的AOP开发)

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>
  == >DefaultAdvisorAutoProxyCreator :

  
  
<!-- 定义切面(带有切点切面) -->
<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. 基于AspectJAOP的开发

:

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

步骤二:引入配置文件:

Log4jspring的配置文件

步骤三:创建包和类:

   
   
cn.green.demo5
UserDao
UserDaoImpl

步骤四:定义切面:

切面:就是切点和通知组合.

 在哪些类的哪些方法上使用增强.

 

定义切面:

   
   
 @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;
 
@Aspect
public 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.xsd
http://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;
@Test
public 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    基于XMLAspectJ骤一:引入AspectJ的相应jar:

aspectJ的开发需要依赖aop的环境.

   
   
引入aspectJjar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
引入spring整合aspectJjar包:spring-aspects-3.2.0.RELEASE.jar

步骤二:引入配置文件:

Log4jspring的配置文件

步骤三:创建包和类:

   
   
cn.spring3.demo2
OrderDao

步骤四:编写切面类:

   
   
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>

























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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值