Java AOP(面向切面编程)实现

简介: 动态代理AOP概念解释AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
动态代理

AOP概念解释

AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

AOP中的概念

Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象。
joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器。
Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合。
Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知。我们就以CGlibProxyFactory类的代码为例进行说明:

public class CGlibProxyFactory implements MethodInterceptor {
    private Object targetObject; // 代理的目标对象

    public Object createProxyInstance(Object targetObject) {
        this.targetObject = targetObject; 

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.targetObject.getClass()); // 设置目标类为代理对象的父类
        enhancer.setCallback(this);

        return enhancer.create();
    }

    // 从另一种角度看: 整个方法可看作环绕通知
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        PersonServiceBean bean = (PersonServiceBean)this.targetObject;
        Object result = null; 
        if (bean.getUser() != null) { // 有权限
            // ...... advice() ----> 前置通知(所谓通知,就是我们拦截到业务方法之后所要干的事情)
            try {
                result = methodProxy.invoke(targetObject, args); // 把方法调用委派给目标对象
                // ...... afteradvice() ----> 后置通知
            } catch (RuntimeException e) {
                // ...... exceptionadvice() ----> 异常通知
            } finally {
                // ...... finallyadvice() ----> 最终通知
            }
        }
        return result;
    }
}

Target(目标对象):代理的目标对象。
Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入。
Introduction(引入):在不修改类代码的前提下,Introduction可以在运行期为类(代理类)动态地添加一些方法或Field。
AOP带来的好处:降低模块的耦合度;使系统容易扩展;更好的代码复用性。

2. JDK实现

1). 创建Person接口

public interface PersonService {
    /**
     * 保存
     * @param name 名称
     */
    public void save(String name);
    /**
     * 根据ID更新名称
     * @param name 姓名
     * @param personId 人员ID
     */
    public void update(String name, Integer personId);
    /**
     * 根据ID获取名称
     * @param personId 人员ID
     * @return 名称
     */
    public String getPersonName(Integer personId);
}

2). 创建实现Person接口的实现类PersonImpl


public class PersonServiceImpl implements PersonService{
    private String user = null;
    
    public void setUser(String user) {
        this.user = user;
    }
    
    public String getUser() {
        return user;
    }
    
    public PersonServiceImpl() {    }
    
    public PersonServiceImpl(String user){
        this.user = user;
    }
    
    @Override
    public void save(String name) {
        System.out.println("我是save方法");
    }

    @Override
    public void update(String name, Integer personId) {
        System.out.println("我是update方法");
    }

    @Override
    public String getPersonName(Integer personId) {
        System.out.println("我是getPersonName方法");
        return "xxx";
    }

}

3). 创建代理类PersonServiceImplProxy

public class PersonServiceImplProxy implements InvocationHandler {
    private PersonService personService;
    
    public PersonService createProxy(PersonService personService) {
        return (PersonService) Proxy.newProxyInstance(PersonServiceImplProxy.class.getClassLoader(), personService.getClass().getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        PersonServiceImpl pImpl = (PersonServiceImpl) this.personService;
        Object result = null;
        // 如果不等于null则表示有权限
        if (null != pImpl.getUser()) {
            // 执行方法
            result = method.invoke(personService, args);
        }
        return result;
    }

}

4). 创建Demo类测试

public class Demo {
    public static void main(String[] args) {
        PersonServiceImplProxy proxy = new PersonServiceImplProxy();
        PersonService service = proxy.createProxy(new PersonServiceImpl("mazaiting"));
        service.save("123");
    }
}

打印结果:


img_ca0e299488614528fc451f48b4161d2a.png
图1.png

5). 更改测试代码

public class Demo {
    public static void main(String[] args) {
        PersonServiceImplProxy proxy = new PersonServiceImplProxy();
        PersonService service = proxy.createProxy(new PersonServiceImpl());
        service.save("123");
    }
}

打印结果:


img_c421a47be207ed9702e326055ebbef75.png
图2.png

3. CGlib实现AOP功能

动态代理技术只能是基于接口,那如果这个对象没有接口,就要使用CGlib这个工具包。

1). 创建PersonService类

public class PersonService {
    private String user = null;
    
    public void setUser(String user) {
        this.user = user;
    }
    
    public String getUser() {
        return user;
    }
    
    public PersonService() {    }
    
    public PersonService(String user){
        this.user = user;
    }
    
    public void save(String name) {
        System.out.println("我是save方法");
    }

    public void update(String name, Integer personId) {
        System.out.println("我是update方法");
    }

    public String getPersonName(Integer personId) {
        System.out.println("我是getPersonName方法");
        return "xxx";
    }
}

2). 创建CGlibProxyFactory类

public class CGlibProxyFactory implements MethodInterceptor {
    // 代理的目标对象
    private Object targetObject;
    
    public Object createProxyInstance(Object targetObject) {
        this.targetObject = targetObject;
        
        // 该类用于生成代理对象
        Enhancer enhancer = new Enhancer();
        // 设置目标类为代理对象的父类
        enhancer.setSuperclass(this.targetObject.getClass());
        // 设置回调用对象本身
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        PersonService service = (PersonService) this.targetObject;
        Object result = null;
        // 有权限
        if (null != service.getUser()) {
            // 把方法调用委派给目标对象
            result = methodProxy.invoke(targetObject, args);
        }
        return result;
    }
}

3). 创建Demo测试类

public class Demo {
    public static void main(String[] args) {
        CGlibProxyFactory factory = new CGlibProxyFactory();
        PersonService service = (PersonService) factory.createProxyInstance(new PersonService("mazaiting"));
        service.save("999");
    }
}

4). 打印结果


img_c90cdb49528869f0617e09a4185d4fa5.png
图3.png
目录
相关文章
|
9月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
331 6
|
9月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
450 1
|
10月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
1396 2
|
9月前
|
安全 前端开发 Java
从反射到方法句柄:深入探索Java动态编程的终极解决方案
从反射到方法句柄,Java 动态编程不断演进。方法句柄以强类型、低开销、易优化的特性,解决反射性能差、类型弱、安全性低等问题,结合 `invokedynamic` 成为支撑 Lambda 与动态语言的终极方案。
347 0
|
10月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
864 0
|
10月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
628 100
|
9月前
|
监控 Java Spring
AOP 切面编程
AOP(面向切面编程)通过动态代理在不修改源码的前提下,对方法进行增强。核心概念包括连接点、通知、切入点、切面和目标对象。常用于日志记录、权限校验、性能监控等场景,结合Spring AOP与@Aspect、@Pointcut等注解,实现灵活的横切逻辑管理。
2180 6
AOP 切面编程
|
9月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
10月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
615 16
|
10月前
|
NoSQL Java 关系型数据库
超全 Java 学习路线,帮你系统掌握编程的超详细 Java 学习路线
本文为超全Java学习路线,涵盖基础语法、面向对象编程、数据结构与算法、多线程、JVM原理、主流框架(如Spring Boot)、数据库(MySQL、Redis)及项目实战等内容,助力从零基础到企业级开发高手的进阶之路。
654 1