spring aop

简介:

什么是AOP

AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

 

AOP使用场景

AOP用来封装横切关注点,具体可以在下面的场景中使用:

Authentication 权限

Caching 缓存

Context passing 内容传递

Error handling 错误处理

Lazy loading 懒加载

Debugging  调试

logging, tracing, profiling and monitoring 记录跟踪 优化 校准

Performance optimization 性能优化

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务

 

Spring AOP底层技术

 

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。

 

动态代理利用反射的原理,给对象动态的生产代理对象,在执行的方法前后来执行相关内容:

复制代码
/**
* 动态代理类
* 
* @author yanbin
* 
*/

public class DynamicProxy implements InvocationHandler {

     /** 需要代理的目标类 */
    private Object target;
/**
     * 写法固定,aop专用:绑定委托对象并返回一个代理类
     * 
     * @param delegate
     * @return
     */

    public Object bind(Object target) {
       this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

     /**
     * @param Object
     *            target:指被代理的对象。
     * @param Method
     *            method:要调用的方法
     * @param Object
     *            [] args:方法调用时所需要的参数
     */

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        // 切面之前执行
        System.out.println("切面之前执行");
        // 执行业务
        result = method.invoke(target, args);
       // 切面之后执行
        System.out.println("切面之后执行");
        return result;
    }
}
复制代码

CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式

复制代码
/**
* 使用cglib动态代理
* 
* @author yanbin
* 
*/

public class CglibProxy implements MethodInterceptor {
 
    private Object target; 

    /**
     * 创建代理对象
     * 
     * @param target
     * @return
     */

    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 回调方法
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object result = null;
        System.out.println("事物开始");
        result = methodProxy.invokeSuper(proxy, args);
        System.out.println("事物结束");
        return result;
    } 
}
复制代码

 

 

AOP相关概念

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。

 

连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

 

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice

 

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

 

引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口

 

目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

 

AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

 

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

 

几种实现方式

1、基于代理的AOP

2、纯简单java对象切面

3、@Aspect注解形式的

4、注入形式的Aspcet切面

 

面先写一下几个基本的类。

接口类:

复制代码
/**
* 定义一个接口
* @author 陈丽娜
* @version 2015年5月31日上午9:16:50
*/

public interface Sleepable {

/**
* 睡觉方法
* @author 陈丽娜
* @version 2015年5月31日上午9:17:14
*/

void sleep();

}
复制代码

实现类:

复制代码
/**
* 陈丽娜 本人实现睡觉接口
* @author 陈丽娜
* @version 2015年5月31日下午4:51:43
*/

public class ChenLliNa implements Sleepable {

@Override
public void sleep() {
// TODO Auto-generated method stub
        System.out.println("乖,该睡觉了!");
}
}
复制代码

 

增强类:

复制代码
/**
* 定义一个睡眠的增强 同时实现前置 和后置
* @author 陈丽娜
* @version 2015年5月31日上午9:24:43
*/

public class SleepHelper implements MethodBeforeAdvice, AfterReturningAdvice {

 
@Override
public void afterReturning(Object returnValue, Method method,Object[] args, Object target) throws Throwable {
   System.out.println("睡觉前要敷面膜");
}

 @Override
public void before(Method method, Object[] args, Object target)throws Throwable {
   System.out.println("睡觉后要做美梦");
}
}
复制代码

 

1、基于代理的AOP

复制代码
<!-- 创建一个增强 advice -->

       <bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper"/>
       <bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>
       <!-- 定义切点   匹配所有的sleep方法-->
       <bean id ="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
             <property name="pattern" value=".*sleep"></property>
       </bean>
     
       <!-- 切面 增强+切点结合 -->
       <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
            <property name="advice" ref="sleepHelper"/>
            <property name="pointcut" ref="sleepPointcut"/>
       </bean>      

       <!-- 定义代理对象 -->
       <bean id="linaProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
               <property name="target" ref="lina"/>
               <property name="interceptorNames" value="sleepHelperAdvisor"/>
       </bean>
复制代码

 

如配置文件中:

pattern属性指定了正则表达式,他匹配所有的sleep方法

使用org.springframework.aop.support.DefaultPointcutAdvisor的目的是为了使切点和增强结合起来形成一个完整的切面

最后配置完后通过org.springframework.aop.framework.ProxyFactoryBean产生一个最终的代理对象。

 

2、纯简单java对象切面

纯简单java对象切面这话怎么说呢,在我看来就是相对于第一种配置,不需要使用代理,,而是通过spring的内部机制去自动扫描,这时候我们的配置文件就该如下修改:

复制代码
<!-- 创建一个增强 advice -->
       <bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper"/>
       <!-- 目标类 -->
       <bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>

       <!--  配置切点和通知-->
       <bean id ="sleepAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="sleepHelper"></property>
            <property name="pattern" value=".*sleep"/>
       </bean>

       <!-- 自动代理配置 -->
       <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
复制代码

是不是相对于第一种简单了许多,不用再去配置代理了。

 

3、@Aspect注解形式

根据我们的经验也知道,注解的形式相对于配置文件是简单一些的,这时候需要在已有的方法或类上家注解:

复制代码
/**
* 通过注解的方式 添加增强
* @author 陈丽娜
* @version 2015年5月31日上午10:26:13
*/

@Aspect
@Component
public class SleepHelper03 { 
/*@Pointcut("execution(* com.tgb.springaop.service.impl..*(..))")*/
@Pointcut("execution(* *.sleep(..))")
public void sleeppoint(){}

@Before("sleeppoint()")
public void beforeSleep(){
   System.out.println("睡觉前要敷面膜");
}

@AfterReturning("sleeppoint()")
public void afterSleep(){
   System.out.println("睡觉后要做美梦");
}
复制代码

 

配置文件中只需写:

复制代码
<!--扫描包 -->
       <context:component-scan base-package="com.tgb" annotation-config="true"/> 
       <!-- ASPECTJ注解 -->
       <aop:aspectj-autoproxy  proxy-target-class="true" />  
      
       <!-- 目标类 -->
       <bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>
复制代码

 

4、注入形式的Aspcet切面

个人感觉这个是最简单的也是最常用的,也是最灵活的。配置文件如下:

复制代码
<!-- 目标类 -->
       <bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>
       <bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper02"/>
      
       <aop:config>
           <aop:aspect ref="sleepHelper">
                <aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))"/>
                <aop:after method="afterSleep" pointcut="execution(* *.sleep(..))"/>
           </aop:aspect>
       </aop:config>
复制代码

配置文件中提到的SleepHelper02类如下:

复制代码
/**
* 通过注解的方式 添加增强
* @author 陈丽娜
* @version 2015年5月31日上午10:26:13
*/

public class SleepHelper02 {

public void beforeSleep(){
   System.out.println("睡觉前要敷面膜");
}

public void afterSleep(){
   System.out.println("睡觉后要做美梦");
}
}
复制代码

 

参考:http://itindex.net/detail/53556-spring-aop


作者:纯洁的微笑 
出处:www.ityouknow.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 

本文如对您有帮助,还请多帮 【推荐】 下此文。 
如果喜欢我的文章,请关注我的公众号

分类:  spring系列

本文转自纯洁的微笑博客博客园博客,原文链接:http://www.cnblogs.com/ityouknow/p/5329550.html,如需转载请自行联系原作者
目录
相关文章
|
5天前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
|
13天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
56 8
|
2月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
2月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
96 5
|
2月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
91 8
|
2月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
2月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
53 5
|
2月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
59 4
|
3月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
61 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
2月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
51 1