AOP面向切面编程

Posted 十三弦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AOP面向切面编程相关的知识,希望对你有一定的参考价值。

1.AOP

Aop(aspect object programming)面向切面编程
  功能: 让关注点代码与业务代码分离!

关注点

  重复代码就叫做关注点;

切面

  关注点形成的类,就叫切面(类)!

  面向切面编程,就是指对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。

切入点

  执行目标对象方法,动态植入切面代码。

  可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。

  Aop实现的原理就是代理。

2.Spring中的aop编程

1) 先引入aop相关jar文件 (aspectj aop优秀组件)

spring-aop-3.2.5.RELEASE.jar 【spring3.2源码】

aopalliance.jar 【spring2.5源码/lib/aopalliance】

aspectjweaver.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

aspectjrt.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

注意: 用到spring2.5版本的jar文件,如果用jdk1.7可能会有问题。

需要升级aspectj组件,即使用aspectj-1.8.2版本中提供jar文件提供。

2)bean.xml中引入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:context="http://www.springframework.org/schema/context"
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/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="userDao" class="com.juaner.spring.aop.UserDao" />
<bean id="orderDao" class="com.juaner.spring.aop.OrderDao"/>
<bean id="aop" class="com.juaner.spring.aop.Aop"/>
</beans>

2.1注解方式实现aop编程

开启aop注解

<!--开启aop注解-->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

使用注解

@Aspect 指定一个类为切面类

@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式

@Before("pointCut_()") 前置通知: 目标方法之前执行

@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)

@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)

@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行

@Around("pointCut_()") 环绕通知: 环绕目标方法执行

@Aspect //指定为切面类

public class Aop {

//指定切入点表达式,拦截哪些方法,即为哪些类生成代理对象
@Pointcut("execution(* com.juaner.spring.aop.*.*(..))")
public void testPt_(){

}

@Before("testPt_()")
public void begin(){
System.out.println("事务开始!");
}
@After("testPt_()")
public void commite(){
System.out.println("事务提交!");
}
@AfterReturning("testPt_()")//出现异常不执行
public void afterReturning(){
System.out.println("调用目标方法结束!");
}

@AfterThrowing("testPt_()")//出现异常才执行
public void afterThrowing(){
System.out.println("目标方法出现异常!");
}
@Around("testPt_()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前");
Object proceed = pjp.proceed();//执行目标方法
System.out.println("环绕后");
}
}

使用切面类

IUserDao userDao = (IUserDao) ac.getBean("userDao");
userDao.save();

如果userDao实现了接口,则userDao为动态代理对象
否则userDao为cglib代理对象

2.2使用xml方式实现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">
    <bean id="userDao" class="com.juaner.spring.xmlaop.UserDao"></bean>
    <bean id="orderDao" class="com.juaner.spring.xmlaop.OrderDao"/>
    <bean id="aop" class="com.juaner.spring.xmlaop.Aop"></bean>

    <!--aop配置-->
    <aop:config>
        <!--定义一个切入点表达式,拦截哪些方法-->
       <aop:pointcut id="pt" expression="!execution(* com.juaner.spring.xmlaop.OrderDao.*(..))"/>
        <!--切面-->
        <aop:aspect ref="aop">
            <aop:before method="begin" pointcut-ref="pt"/>
            <aop:after method="commite" pointcut-ref="pt"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
            <aop:around method="around" pointcut-ref="pt"/>
        </aop:aspect>
    </aop:config>
</beans>

3.切入点表达式

切入点表达式语法定义如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
          throws-pattern?)
<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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/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">
    
    <!-- dao 实例 -->
    <bean id="userDao" class="cn.itcast.g_pointcut.UserDao"></bean>
    <bean id="orderDao" class="cn.itcast.g_pointcut.OrderDao"></bean>
    
    <!-- 切面类 -->
    <bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean>
    
    <!-- Aop配置 -->
    <aop:config>
        
        <!-- 定义一个切入点表达式: 拦截哪些方法 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>-->
        
        <!-- 【拦截所有public方法】 -->
        <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
        
        <!-- 【拦截所有save开头的方法 】 -->
        <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
        
        <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
        <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
        
        <!-- 【拦截指定类的所有方法】 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
        
        <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
        <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
        
        <!-- 【多个表达式】 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <!-- 下面2个且关系的,没有意义 -->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) &amp;&amp; execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        
        <!-- 【取非值】 -->
        <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
        <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>
        
        <!-- 切面 -->
        <aop:aspect ref="aop">
            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="pt"/>
        </aop:aspect>
    </aop:config>
</beans>    

 

以上是关于AOP面向切面编程的主要内容,如果未能解决你的问题,请参考以下文章

spring切面Aspects

面向切面编程AOP

Spring——面向切面编程AOP

spring aop切面表达式详解及例子

面向切面编程(AOP)

AOP(面向切面编程)初识Demo