`

Spring基础:AOP编程(1)

阅读更多
Java编程中的代理

Spring以IoC为基础,发展了另外一个底层组件,就是AOP。
AOP的含义是“面向切面的编程”,将业务无关的代码但是又和业务缠在一起的代码剥离出去。AOP是一个很复杂的概念,这里只是拿出冰山一角说明一下。

AOP的术语
1.连接点(Joinpoint):程序执行的某一个特定的位置:比如类开始初始化前,初始化后,某个方法调用的前后,方法抛出异常的时候,等等具有某一种边界性质的特定点都可以称之为“连接点”。

2.切点(Pointcut):感兴趣的点的集合,如果说连接点是数据库中存储的数据的话,那切点就是where子句查询出来的目标点了。

3.增强(Advice):有的地方按照字面的意思翻译成通知,这里使用增强更加形象,即对目标对象的功能进行增强。

4.目标对象(Target):即待增强的对象。

5.引介(Introduction):特殊的增强,可以为类添加方法和属性。

6.织入(Weaver):织入就是以某种技术,将增强和目标对象融合起来,构建新类的过程,总结起来有3种织入技术。
  • 编译期织入:需要特殊的Java编译器
  • 类装载期织入:需要特殊的类装载器
  • 动态代理织入:在运行期为目标类添加增强

Spring采用第三种代理织入,所以不需要额外的编译器。

7.代理(Proxy);织入增强之后的目标类生成的新的类。

8.切面(Advisor):由增强和切点组合形成。

现在来看一个带有横切逻辑的实例:
public class ForumServiceImpl implements ForumService {

    public void removeTopic(int topicId) {
        PerformanceMonitor.begin("com.firethewhole.maventest07.proxy.ForumService.Impl.removeTopic");
        System.out.println("模拟删除Topic记录:" + topicId);
        try {
            Thread.currentThread().sleep(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        PerformanceMonitor.end();
    }

    public void removeForum(int forumId) {
        PerformanceMonitor.begin("com.firethewhole.maventest07.proxy.ForumService.Impl.removeForum");
        System.out.println("模拟删除Forum记录:" + forumId);
        try {
            Thread.currentThread().sleep(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        PerformanceMonitor.end();
    }
}

public class PerformanceMonitor {
    private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
    
    public static void begin(String method) {
        System.out.println("begin monitor...");
        MethodPerformance mp = new MethodPerformance(method);
        performanceRecord.set(mp);
    }
    
    public static void end() {
        System.out.println("end monitor...");
        MethodPerformance mp = performanceRecord.get();
        mp.printPerformance();
    }
}

public class MethodPerformance {
    private long begin;
    private long end;
    private String serviceMethod;

    public MethodPerformance(String serviceMethod) {
        this.serviceMethod = serviceMethod;
        this.begin = System.currentTimeMillis();
    }

    public void printPerformance() {
        end = System.currentTimeMillis();
        long elapse = end - begin;
        System.out.println(serviceMethod + "花费" + elapse + "毫秒。");
    }
}

ForumService forumService = new ForumServiceImpl();
forumService.removeForum(10);
forumService.removeTopic(1012);

输出以下信息:

begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumService.Impl.removeForum花费20毫秒。
begin monitor...
模拟删除Topic记录:1012
end monitor...
com.firethewhole.maventest07.proxy.ForumService.Impl.removeTopic花费20毫秒。


这里性能代码和业务代码都在一起,将来修改业务代码的时候,性能监控代码可能也需要同时修改,显的很不清晰。

使用JDK动态代理技术
首先将性能横切代码都删除掉
public class ForumServiceAopStyleImpl implements ForumService {

    public void removeTopic(int topicId) {
        System.out.println("模拟删除Topic记录:" + topicId);
        try {
            Thread.currentThread().sleep(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void removeForum(int forumId) {
        System.out.println("模拟删除Forum记录:" + forumId);
        try {
            Thread.currentThread().sleep(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

public class PerformanceHandler implements InvocationHandler {
    private Object target;
    
    public PerformanceHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        PerformanceMonitor.begin(target.getClass().getName() + "." + method.getName());
        Object obj = method.invoke(target, args);
        PerformanceMonitor.end();
        return obj;
    }
}

在InvocationHandler中创建代理类,在调用ForumServiceAopStyleImpl的方法的时候,可以只能增强逻辑,先执行性能监控代码。接下来看下如何使用
// 加入动态代理的方法
ForumService target = new ForumServiceAopStyleImpl();
PerformanceHandler handler = new PerformanceHandler(target);
ForumService proxy = (ForumService) Proxy.newProxyInstance(
        target.getClass().getClassLoader()
        , target.getClass().getInterfaces()
        , handler);

proxy.removeForum(10);
proxy.removeTopic(1012);


输出结果:

begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl.removeForum花费47毫秒。
begin monitor...
模拟删除Topic记录:1012
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl.removeTopic花费31毫秒。


使用CGLib创建代理
使用JDK自带的InvocationHandler有一个局限性,就是只能针对接口进行代理,如果想直接针对类进行代理的话,就只能使用CGLib了。首先需要加入maven依赖。
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>


public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    
    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        PerformanceMonitor.begin(obj.getClass().getName() + "." + method.getName());
        Object result = proxy.invokeSuper(obj, args);
        PerformanceMonitor.end();
        return result;
    }
}


基于CGLib创建代理类。
// 使用Cglib代理
CglibProxy proxyCglib = new CglibProxy();
ForumServiceAopStyleImpl forumServiceImpl = (ForumServiceAopStyleImpl) proxyCglib.getProxy(ForumServiceAopStyleImpl.class);
forumServiceImpl.removeForum(10);
forumServiceImpl.removeTopic(1023);


输出结果:

begin monitor...
模拟删除Forum记录:10
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl$$EnhancerByCGLIB$$58fbcf09.removeForum花费125毫秒。
begin monitor...
模拟删除Topic记录:1023
end monitor...
com.firethewhole.maventest07.proxy.ForumServiceAopStyleImpl$$EnhancerByCGLIB$$58fbcf09.removeTopic花费32毫秒。


可以看出CGLib创建出来的类的名字还是比较奇怪的,另外还有一点CGLib在创建对象的时候没有Invocation快,不适合需要反复创建对象的场合,在IoC容器启动的时候创建较为合适
分享到:
评论

相关推荐

    Spring基础:AOP编程(4)

    在本篇博客“Spring基础:AOP编程(4)”中,我们将深入探讨Spring框架中的面向切面编程(Aspect-Oriented Programming,简称AOP),这是一个强大的功能,它允许我们在不修改原有业务代码的情况下,实现对系统中横切...

    Spring基础:AOP编程(2)

    在本篇关于“Spring基础:AOP编程(2)”的文章中,我们将深入探讨Spring框架中的面向切面编程(Aspect-Oriented Programming, AOP),这是一种强大的设计模式,它允许我们分离关注点,尤其是那些横切关注点,如日志、...

    Spring基础:AOP编程(5)

    在本篇博文中,我们将深入探讨Spring框架中的一个核心特性——面向切...通过以上介绍,我们对Spring中的AOP编程有了基本了解。在实际开发中,AOP可以帮助我们更好地组织代码,降低复杂度,提高代码的可维护性和可读性。

    Spring基础:AOP编程(3)

    **Spring AOP编程详解** 在Java开发中,Spring框架因其强大的功能和易用性而备受推崇,其中AOP(Aspect-Oriented Programming,面向切面编程)是其核心特性之一。AOP允许开发者将关注点从核心业务逻辑中分离出来,...

    Spring AOP面向方面编程原理:AOP概念

    Spring AOP是在Spring框架的基础上实现的一种面向方面编程机制。 1. **方面(Aspect)**:这是AOP的核心概念之一,指代一个关注点的模块化,该关注点可能会横切多个对象。例如事务管理就是一个典型的横切关注点,...

    Spring基础:Spring AOP简单使用

    Spring AOP,全称Aspect Oriented Programming(面向切面编程),是Spring框架的重要组成部分,它扩展了传统的面向对象编程(OOP),使得开发者能够更好地处理系统中的横切关注点,如日志、事务管理、权限控制等。...

    小马哥讲 Spring AOP 编程思想 - API 线索图.pdf

    在讨论Spring AOP(面向切面编程)时,首先需要理解几个核心概念。Spring AOP 是Spring框架提供的一个功能模块,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中解耦出来,通过在方法调用前后进行...

    hualinux spring 3.15:Spring AOP.pdf

    根据提供的文件内容,可以提取出以下知识点: ...文档中提到的实践示例,例如前置通知、后置通知、返回通知、异常通知和环绕通知的具体编码实现,都是通过具体的代码示例来说明如何在Spring中应用AspectJ进行AOP编程。

    spring-boot aop

    Spring Boot AOP(面向切面编程)是一种强大的设计模式,它允许我们在不修改现有代码的情况下,插入额外的功能或监控代码。在Spring框架中,AOP主要用于日志记录、事务管理、性能统计等场景。本示例是关于如何在...

    spring AOP切面编程

    Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它扩展了传统的面向对象编程,使得开发者可以方便地实现横切关注点,如日志、事务管理、性能监控等。在Spring中,AOP通过代理...

    spring源代码分析:aop的实现

    其中,面向切面编程(Aspect Oriented Programming,简称AOP)是Spring的重要特性之一,它极大地简化了代码中的横切关注点,如日志、事务管理等。本文将深入Spring源码,探索AOP的实现原理。 首先,我们需要理解AOP...

    AOP_使用spring框架进行面向切面编程

    面向切面编程(AOP)是一种编程范式,它旨在减少代码中的重复部分,特别是那些与核心业务逻辑无关但又必须处理...同时,通过分析和操作`springAOP`压缩包中的示例代码,可以更直观地了解AOP在Spring框架中的具体实现。

    Spring中aop编程所需要的jar包

    为了在Spring中进行AOP编程,我们需要一些特定的JAR包。以下是对这些关键组件的详细说明: 1. **Spring核心包**: - `spring-core.jar`: 这是Spring框架的基础,包含了IoC(Inversion of Control,控制反转)容器...

    Spring切面AOP编程的简单模拟实现

    在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从核心业务逻辑中分离出来,例如日志记录、事务管理等。本教程将通过模拟Spring AOP来阐述如何实现一个简单的切面编程。我们将讨论...

    spring2-aop.pdf

    Spring 的核心特性包括依赖注入(Dependency Injection, DI)和面向切面编程(Aspect-Oriented Programming, AOP),这些特性有助于提高代码的可维护性和可扩展性。 #### 二、面向切面编程 (AOP) 原理与实践 ##### ...

    spring-aop-jar

    在IT领域,Spring框架是一个广泛使用的Java应用框架,它提供了许多功能,包括依赖注入、面向切面编程(AOP)等。"spring-aop-jar"这个主题涉及到Spring框架中的核心组件之一——Spring AOP。这里我们将深入探讨...

    使用动态代理演示Spring的AOP编程原理

    为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...

    Spring4—AOP编程

    Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的一个重要特性,主要用于解决程序中的横切关注点,如日志、事务管理、安全性等。AOP通过将这些关注点与核心业务逻辑分离,实现了代码的...

    spring aop 编程所需要的搜友JAR包

    Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的核心概念是切面(Aspect)、通知(Advice)、连接点...

Global site tag (gtag.js) - Google Analytics