千家信息网

Spring AOP之简单实践

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,Spring AOP建立在代理之上,所以先对代理有个简单的认识也是很有必要的,下面结合代码来进行简要说明。1,首先定义一个接口和实体对象public class Student { public
千家信息网最后更新 2026年11月04日Spring AOP之简单实践

Spring AOP建立在代理之上,所以先对代理有个简单的认识也是很有必要的,下面结合代码来进行简要说明。

1,首先定义一个接口和实体对象

public class Student {    public String name ;    public int age ;}public interface IStudentService {    /**     * 添加学生     * */    void addStudent(Student student) ;    /**     * 删除学生     * */    void removeStudent(String studentId) ; }public class DefaultStudentService implements IStudentService {    @Override    public void addStudent(Student student) {        System.out.println("新增学生信息");    }    @Override    public void removeStudent(String studentId) {        System.out.println("删除ID为" + studentId+"的学生信息");    }}

2,Java的动态代理技术

Java的动态代理主要涉及到下面两个类型
1)java.lang.reflect.InvocationHandler接口

/**代理实例的调用处理程序实现的接口;每个代理实例都有一个关联的调用处理程序。在代理实例上调用方法时,方法调用将被处理并发送到其调用处理程序的invoke方法。*/public interface InvocationHandler {    /**            @param proxy 动态生成的代理对象实例            @param method 被代理对象调用的方法            @param args 被调用的方法的参数            @return 从代理实例上的方法调用返回的值,其类型必须和被代理接口中所定义的返回类型兼容。    */    public Object invoke(Object proxy, Method method, Object[] args)        throws Throwable;}

2)java.lang.reflect.Proxy对象

简单的说,Java动态代理就是通过Java的Proxy对象来创建某个实例对象的代理对象,在调用代理对象的时候便会触发调用InvocationHandler的invoke方法,我们在invoke方法中可以添加一些额外的代码来扩充能力,同时在invoke中我们可以判断哪个方法被调用,然后通过反射执行被代理对象上的这个方法。

3,使用Java动态代理实例

/**     * Java的动态代理技术【代理整个接口类】     */    public static void javaDyncProxy() {        // 要被代理的目标对象        DefaultStudentService studentService = new DefaultStudentService();        // 代理的调用处理器【当我们通过动态代理对象调用任何一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用】        StudentServiceInvocationHandler invocationHandler = new StudentServiceInvocationHandler(studentService);        // 创建代理对象        IStudentService service = (IStudentService)Proxy.newProxyInstance(studentService.getClass().getClassLoader(),                studentService.getClass().getInterfaces(), invocationHandler);        service.addStudent(new Student());    }    public static class StudentServiceInvocationHandler implements InvocationHandler {        private IStudentService target;        public StudentServiceInvocationHandler(IStudentService studentService) {            this.target = studentService;        }        /*         * @param proxy         * 真实对象的真实代理对象;InvocationHandler本身,例如这里的:StudentServiceInvocationHandler         */        @Override        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {            System.out.println("是的,你已经是在使用Proxy了");            return method.invoke(target, args);        }    }    public static void main(String[] args) {         javaDyncProxy() ;    }

执行main方法后,得到的打印输入如下

是的,你已经是在使用Proxy了新增学生信息

4,Spring AOP

前面的文章中有介绍过Spring AOP中的一些概念,其中包括Advice和Pointcut。 Pointcut用于筛选类和方法,而Advice负责确实执行点,通过两则的结合就有了Advisor(切面)。

我们先看下SpringAOP中这些对象的关系。

由上图可知
1)Pointcut接口依赖于ClassFilter和MethodMatcher两个接口,通过这两个接口来达到筛选类和方法的目的
2)Advice接口【是个Tag Interface】包含了众多的子接口,通过子接口来扩展其功能,每个子接口都分别代表不同的方法执行点(内部的抽象方法便是添加增强代码的地方)
3)Adisor接口依赖于Advice接口,代表一个类中的所有方法的某些执行点,其最常用的子接口类型PointcutAdvisor有添加了对Pointcut接口的依赖,表示某些类中某些方法的某些执行点

下面我们更进一步的看看各个接口都有哪些实现

Pointcut实现类关系图

Advice接口关系图

ThrowsAdvice是一个Tag interface,实现类具有以下任意一个或多个方法实现均可:
public void afterThrowing(Exception ex)
public void afterThrowing(RemoteException)
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

Advisor关系图

上面通过类图展现了SpringAOP中几个关键概念间的关系,下面再看看SpringProxy的类图

1)ProxyCreatorSupport与AopProxyFactory关联,在内部默认创建DefaultAopProxyFactory对象

2)AopProxyFactory依赖AopProxy接口,AopProxy的实现类包含了基于Java动态代理的JdkDynamicAopProxy和基于cglib的CglibAopProxy对象

3)我们在使用AopProxy的时候,内部会根据我们的设置来动态的选择使用Java动态代理还是基于cglib的代理。

下面通过示例代码来说明Spring Aop的以上这些对象

使用ProxyFactory
/** * 定义"方位"以及对应的增强代码。 * 使用时,如果没提供具体的Ponitcut,该增强会织入到目标类的所有方法上。 * */public class StudentServiceAdvice implements MethodBeforeAdvice, AfterReturningAdvice,ThrowsAdvice {    @Override    public void before(Method method, Object[] args, Object target) throws Throwable {        System.out.println("调用方法" + method.getName() +"前");    }    @Override    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {        System.out.println("调用方法" + method.getName() +"返回后");    }    /**     * 方法名必须是afterThrowing,前三个参数是可选【同时都出现或都不出现】,最后个参数不行是Throwable或子类。     * 可以定义多个afterThrowing方法,Spring会自动选用最匹配的增强方法。     * */    public void afterThrowing(Method method, Object[] args, Object target,RuntimeException e) {        System.out.println("调用方法" + method.getName() +"抛出异常后");    }}
/**     * 只用增强应用到类上的所有方法上     */    public static void springProxy() {        // 要被代理的目标对象        DefaultStudentService studentService = new DefaultStudentService();        /*         * 代理工厂根据代理配置在内部使用AopProxy类型的代理创建代理对象,AopProxy的实现类有以下两个:          * 1)JdkDynamicAopProxy :基于Java的动态代理技术          * 2)Cglib2AopProxy : 基于CGLib的动态代理技术         * 在使用ProxyFactory的时候,如果通过setInterface()方法指定目标接口进行代理,则使用JdkDynamicAopProxy;         * 如果针对类的代理或者设置SetOptimize(true),则使用Cglib2AopProxy;         */        ProxyFactory factory = new ProxyFactory();        // 设置要被代理的接口类型        factory.setInterfaces(studentService.getClass().getInterfaces());        // 设置代理的目标对象        factory.setTarget(studentService);        // 为代理目标添加增强[Advice包含了横切代码和连接点信息,所以本身就是一个简单的切面]        factory.addAdvice(new StudentServiceAdvice());        // 生成代理实例        IStudentService proxy = (IStudentService) factory.getProxy();        // 调用方法        proxy.addStudent(new Student("test", 22));        proxy.removeStudent("10001");    }
执行后的输出结果:
调用方法addStudent前新增学生信息调用方法addStudent返回后调用方法removeStudent前删除ID为10001的学生信息调用方法removeStudent返回后
使用AspectJProxyFactory
                            org.aspectj            aspectjweaver            1.9.4                            org.aspectj            aspectjrt            1.9.4        
@Aspectpublic class CommAspect {    /**     * 前置增强     * 所有目标类中的所有addStudent方法     * */    @Before("execution (* addStudent(..))")    public void defore(JoinPoint joinPoint) {        System.out.println(">>>>befor addStudent");    }}public static void springAspectProxy() {        // 要被代理的目标对象        DefaultStudentService studentService = new DefaultStudentService();        // 基于AspectJ的代理工厂        AspectJProxyFactory factory = new AspectJProxyFactory();        // 设置代理目标        factory.setTarget(studentService);        // 添加切面类        factory.addAspect(CommAspect.class);        // 生成代理实例        IStudentService proxy = (IStudentService) factory.getProxy();        // 调用方法        proxy.addStudent(new Student("test", 22));        proxy.removeStudent("10001");    }

执行后输出:

>>>>befor addStudent新增学生信息删除ID为10001的学生信息
代理 方法 对象 接口 动态 学生 实例 目标 信息 代码 类型 处理 两个 技术 时候 切面 参数 程序 生成 代表 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 中关村互联网 科技集团 金融科技创新监管互联网金融 互联网金融与金融科技 西安互联网科技 互联网与未来科技 唐信互联网科技 大连 滨湖区互联网智能科技产品供应 互联网科技实习生岗位职责 佳云科技和互联网广告 长沙茂晟互联网科技有限公司 上海京穆互联网科技有限公司 元气玛特互联网科技公司是外包吗 云南省自由互联网科技有限公司 扫呗互联网科技有限公司 万物互联网智能科技 艺电能源互联网科技有限公司招聘 众联互联网络科技 互联网领先科技成果宣传视频 互联网科技自媒体灵感 互联网 科技节活动 微视频大赛 新华互联网科技学校 互联网最新的科技 互联网金融科技创新 居家互联网科技有限公司 汽车互联网创新科技园 互联网校园科技培训 东营紫格互联网科技 中国科技和美国互联网 三亚科技创新互联网基地 亚光科技低轨卫星互联网
0