spring AOP面向切面编程学习笔记

一、面向切面编程简介:

在调用某些类的方法时,要在方法执行前或后进行预处理或后处理;预处理或后处理的操作被封装在另一个类中。如图中,UserService类在执行addUser()或updateUser方法前开启事务,执行完后要提交事务;而几乎所有数据库操作都是如此,那么就可以将事务操作的方法提取出封装到一个类里。然后再利用代理类进行处理(目标类方法增强),返回代理类对象

二、AOP相关术语

Target:目标类,需要被增强的类。

JoinPoint:连接点,目标类上需要被增强的方法。(这些方法可以被增强,也可能不增强)。

PointCut:切入点,被增强的连接点(已经增强了)。切入点术语特殊的连接点

Advice:增强/通知,增强的方法。

weaving:织入,将切入点和通知结合,生成代理类过程。

Proxy:代理类。

Aspect:切面,切入点和通知结合形成的面

三、JDK动态代理模拟AOP

1、项目结构(接口+目标类+切面类+代理类+测试类)

2、新建接口UserService

package hjp.springAOP.jdkProxy;

public interface UserService {
    void addUser();

    void updateUser();
}

UserService

3、新建目标类UserServiceImpl,并实现接口UserService

package hjp.springAOP.jdkProxy;

public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        // TODO Auto-generated method stub
        System.out.println("jdk add user");
    }

    @Override
    public void updateUser() {
        // TODO Auto-generated method stub
        System.out.println("jdk update user");
    }

}

UserServiceImpl

4、新建切面类MyAspect

package hjp.springAOP.jdkProxy;

/**
 * 切面类,用于存放增强
 *
 * @author JiaPeng
 *
 */
public class MyAspect {
    public void beafore() {
        System.out.println("before");
    }

    public void after() {
        System.out.println("after");
    }
}

MyAspect

5、新建代理类MyFactory

package hjp.springAOP.jdkProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 工厂生成代理类,目的:将目标类(切入点)和切面类(通知)结合。
 *
 * @author JiaPeng
 *
 */
public class MyFactory {
    public static UserService createService() {
        // 创建目标类
        final UserService userService = new UserServiceImpl();
        // 创建切面类
        final MyAspect myAspect = new MyAspect();
        // 使用jdk动态代理,生成代理类
        // 第一个参数是,当前类下的类加载器,第二个参数是目标类所继承的接口数组,第三个参数是匿名内部类
        // 匿名内部类也就是没有名字的内部类;正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写;但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
        UserService proxyService = (UserService) Proxy.newProxyInstance(MyFactory.class.getClassLoader(),
                userService.getClass().getInterfaces(), new InvocationHandler() {
                    // 代理类每一个方法执行时,都将调用处理类的invoke方法
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        // 执行前通知
                        myAspect.beafore();
                        // 执行目标类的相应方法
                        Object obj = method.invoke(userService, args);
                        // 执行后通知
                        myAspect.after();
                        return obj;
                    }
                });
        return proxyService;
    }
}

代理类

6、新建测试类

package hjp.springAOP.jdkProxy;

import org.junit.Test;

public class TestApp {
    @Test
    public void demo1() {
        UserService userService = MyFactory.createService();
        userService.addUser();
        userService.updateUser();
    }
}

测试类

四、CGLIB模拟AOP

cglib 字节码增强工具,一般框架都使用。只要有类就可以增强

1、项目结构(cglib的jar包已被spring打包好了,所以添加了spring的主要jar包就可以了)

2、新建目标类UserServiceImpl,没有接口

package hjp.springAOP.cglibProxy;

public class UserServiceImpl {

    public void addUser() {
        System.out.println("cglib add user");
    }

    public void updateUser() {
        System.out.println("cglib update user");
    }

}

UserServiceImpl

3、新建切面类

package hjp.springAOP.cglibProxy;

/**
 * 切面类,用于存放增强
 *
 * @author JiaPeng
 *
 */
public class MyAspect {
    public void beafore() {
        System.out.println("before");
    }

    public void after() {
        System.out.println("after");
    }
}

切面类

4、新建代理类

package hjp.springAOP.cglibProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.eclipse.jdt.internal.compiler.classfmt.FieldInfoWithAnnotation;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/**
 * 工厂生成代理类,目的:将目标类(切入点)和切面类(通知)结合。
 *
 * @author JiaPeng
 *
 */
public class MyFactory {
    public static UserServiceImpl createService() {
        // 创建目标类
        final UserServiceImpl userServiceImpl = new UserServiceImpl();
        // 创建切面类
        final MyAspect myAspect = new MyAspect();
        // 使用cglib创建代理类,其实现方式就是在cglib运行时,动态创建目标类子类(该子类就是代理类,Java动态代理是基于接口或父类的)
        // 创建核心类
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(userServiceImpl.getClass());
        // 代理类方法将调用回调函数,等效JDK InvocationHandler
        // 接口Callback,子接口MethodInterceptor对方法进行增强
        enhancer.setCallback(new MethodInterceptor() {

            @Override
            // 前三个参数与jdk动态代理invoke相同
            // 第四个参数是方法代理
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
                    throws Throwable {
                // TODO Auto-generated method stub
                // 切面类的前通知
                myAspect.beafore();
                // 目标方法
                //Object object = method.invoke(userServiceImpl, args);
                Object object = methodProxy.invokeSuper(proxy, args);//执行代理类(子类)父类方法(父类就是目标类),效果和上面的一样
                // 切面类后通知
                myAspect.after();
                return object;
            }
        });
        // 创建代理类
        return (UserServiceImpl) enhancer.create();
    }
}

代理类

5、新建测试类

package hjp.springAOP.cglibProxy;

import org.junit.Test;

public class TestApp {
    @Test
    public void demo1() {
        UserServiceImpl userService = MyFactory.createService();
        userService.addUser();
        userService.updateUser();
    }
}

测试类

时间: 2024-08-07 01:06:12

spring AOP面向切面编程学习笔记的相关文章

深入探索spring技术内幕(七): 配置Spring AOP面向切面编程

一. AOP一些概念 Aspect( 切面 ): 指横切性关注点的抽象即为切面, 它与类相似, 只是两者的关注点不一样, 类是对物体特征的抽象, 而切面横切性关注点的抽象. joinpoint( 连接点 ): 指那些被拦截到的点. 在spring中, 这些点指的是方法, 因为spring只支持方法类型的连接点, 实际上joinpoint还可以是field或类构造器) Pointcut( 切入点 ): 指我们要对那些joinpoint进行拦截的定义. Advice( 通知 ): 指拦截到joinp

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

从源码入手,一文带你读懂Spring AOP面向切面编程

之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代理. 基于这两者的实现上,这次来探索下Spring的AOP原理.虽然AOP是基于Spring容器和动态代理,但不了解这两者原理也丝毫不影响理解AOP的原理实现,因为大家起码都会用. AOP,Aspect Oriented Programming,面向切面编程.在很多时候我们写一些功能的时候,不需要用到继承这么

Spring AOP 面向切面编程

AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 在Spring中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例

【Spring系列】Spring AOP面向切面编程

前言 接上一篇文章,在上午中使用了切面做防重复控制,本文着重介绍切面AOP. 在开发中,有一些功能行为是通用的,比如.日志管理.安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关注点(cross-cutting concerns). DI(依赖注入)有助于应用对象之间的解耦,而AOP可以实现横切关注点与他们所影响的对象之间的解耦. 面向切面编程在Spring AOP中有4种类型的调用,方法调用的之前.后.异常增加其他方法,方法调用的前和后调用其他方法,将方法中的参数传递给其

十二.Spring AOP面向切面编程

什么是AOP? AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP的第一个案例 要求:使用AOP实现日志记录功能,核心模块和增强单独开发,运行时组装 1.创建接口HelloDao.HelloService. 创建接口类HelloDaoImpl.HelloServiceImpl并实现dao层接口 public interface IHolleDao { public void print

Spring AOP面向切面编程详解

前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添加注解方式实现AOP的话,并不推荐使用XML方式.换言之在XML方式配置更适用于不能对代码添加注解的情况下(注解配置方式推荐值>XML配置方式推荐值) AOP相关术语 1.通知(Advice):在切面的某个特定的连接点上执行的动作,即当程序到达一个执行点后会执行相对应的一段代码,也称为增强处理.通知

Spring AOP(面向切面编程)

AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理.日志管理.权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性. 简单例子:在某个项目里,非管理员不能对某些业务进行操作,代码如下: 从上面的代码我们可以看出这种方式达到了权限验证的功能,但是如果有100个方法的话,就会显得冗余,代码不好维护,这是传统的硬编码方式 我们对代码进行改进(以注解的方式) 1,新建一个切面(Aspect) @Pointcut是切入点,我需要切入那

详细解读 Spring AOP 面向切面编程(一)

今天我要和大家分享的是 AOP(Aspect-Oriented Programming)这个东西,名字与 OOP 仅差一个字母,其实它是对 OOP 编程方式的一种补充,并非是取而代之.翻译过来就是"面向方面编程",可我更倾向于翻译为"面向切面编程".它听起有些的神秘,为什么呢?当你看完这篇文章的时候,就会知道,我们做的很重要的工作就是去写这个"切面" .那么什么是"切面"呢? 没错!就是用一把刀来切一坨面.注意,相对于面而言,