【框架】[Spring]AOP拦截-三种方式实现自动代理

简介: 【框架】[Spring]AOP拦截-三种方式实现自动代理

这里的自动代理,我讲的是自动代理bean对象,其实就是在xml中让我们不用配置代理工厂,也就是不用配置class为org.springframework.aop.framework.ProxyFactoryBean的bean。

总结了一下自己目前所学的知识。

发现有三种方式实现自动代理

用Spring一个自动代理类DefaultAdvisorAutoProxyCreator:

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

例如:

原来不用自动代理的配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    <!-- 代理前原对象 -->
    <bean id="person" class="cn.hncu.xmlImpl.Person"></bean>
    <!-- 切面 = 切点+通知 -->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 切点 -->
        <property name="patterns">
            <list>
                <value>.*run.*</value>
            </list>
        </property>
        <!-- 通知-由我们写,实际代理动作 -->
        <property name="advice">
            <bean id="advice" class="cn.hncu.xmlImpl.AroundAdvice"></bean>
        </property>
    </bean>
    <!-- 代理工厂 -->
    <bean id="personProxied" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 放入原型对象 -->
        <property name="target" ref="person"></property>
        <!-- 放入切面 -->
        <property name="interceptorNames">
            <list>
                <value>advisor</value>
            </list>
        </property>
    </bean>
</beans>

现在改用自动代理,如下配置:

<beans ...>
<!-- 代理前原对象 -->
    <bean id="person" class="cn.hncu.xmlImpl.Person"></bean>
    <!-- 切面 = 切点+通知 -->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 切点 -->
        <property name="patterns">
            <list>
                <value>.*run.*</value>
            </list>
        </property>
        <!-- 通知-由我们写,实际代理动作 -->
        <property name="advice">
            <bean id="advice" class="cn.hncu.xmlImpl.AroundAdvice"></bean>
        </property>
    </bean>
    <!-- 自动代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
</beans>

测试方法

@Test//自动代理
    public void demo4(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/4.xml");
        //我们直接在这里获取Person对象就可以了,因为在最开始xml文件newPerson对象后,Spring就已经帮我们代理了!
        Person p =ctx.getBean(Person.class);
        p.run();
        p.say();
    }

相对于前面,也就是把代理工厂部分换成自动代理了。

演示结果:

image.png

自己写一个自动代理底层实现:

我们也可以写一个类,来实现DefaultAdvisorAutoProxyCreator自动代理的功能!

首先,我们需要实现一个接口,也就是BeanPostProcessor接口。

BeanPostProcessor接口作用是:如果我们需要在Spring容器完成Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中。

而我们想要在原型对象bean被创建之后就代理了,就必须在原来的容器中拿到原来的原型对象,需要拿到原来spring容器中的切面对象,这个时候,我们就需要原来的容器,这个时候就需要另一个接口,也就是ApplicationContextAware接口!

通过这2个接口,我们就可以实现自动代理了。

package cn.hncu.xmlImpl;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MyAutoProxy implements BeanPostProcessor,ApplicationContextAware{
    private ApplicationContext applicationContext=null;
    //bean创建之前调用
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;//在这里,我们直接放行
    }
    //bean创建之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        ProxyFactoryBean factory = new ProxyFactoryBean();
        //把原型对象放入代理工厂
        factory.setTarget(bean);
        //在这里
        Advisor adv = applicationContext.getBean(Advisor.class);
        factory.addAdvisor(adv);
        //返回被代理后的对象
        return factory.getObject();
    }
    //拿到原来的spring中的容器
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext=applicationContext;
    }
}

5.xml

<beans...>
<!-- 代理前原对象 -->
    <bean id="person" class="cn.hncu.xmlImpl.Person"></bean>
    <!-- 切面 = 切点+通知 -->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 切点 -->
        <property name="patterns">
            <list>
                <value>.*run.*</value>
            </list>
        </property>
        <!-- 通知-由我们写,实际代理动作 -->
        <property name="advice">
            <bean id="advice" class="cn.hncu.xmlImpl.AroundAdvice"></bean>
        </property>
    </bean>
    <!-- 自己写的自动代理 -->
    <bean class="cn.hncu.xmlImpl.MyAutoProxy"></bean>
</beans>

测试方法:

@Test//自己实现的自动代理
    public void demo5(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/5.xml");
        Person p =ctx.getBean(Person.class);
        p.run();
        p.say();
    }

测试结果就不上图了,和前面是一样的。

其实很多时候,我们如果自己去练一下底层,对上层的框架更好理解。

还有一种方法。

使用aop标签配自动代理

需要在beans加一个命名空间

xmlns:aop="http://www.springframework.org/schema/aop"

还需要配xsi:schemaLocation,为aop加一个网络地址。

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd

我们需要一个aspectjweaver-jar包:

下载地址:

http://mvnrepository.com/artifact/org.aspectj

xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd ">
    <!-- 利用sop标签实现自动代理 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- 代理前原对象 -->
    <bean id="person" class="cn.hncu.xmlImpl.Person"></bean>
    <!-- 切面 = 切点+通知 -->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 切点 -->
        <property name="patterns">
            <list>
                <value>.*run.*</value>
            </list>
        </property>
        <!-- 通知-由我们写,实际代理动作 -->
        <property name="advice">
            <bean id="advice" class="cn.hncu.xmlImpl.AroundAdvice"></bean>
        </property>
    </bean>
</beans>

测试方法:

@Test//自动代理
    public void demo6(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/6.xml");
        Person p =ctx.getBean(Person.class);
        p.run();
        p.say();
    }

测试结果:

image.png

个人觉得能学会使用一种就OK了,不用全部记下来,为了学习,都了解一下就好,别人写出来,能看懂就好。

哈哈,其实底层学好了,自己写的时候,就算不会用Spring的自动代理,自己写出来底层也是蛮好的嘛

目录
相关文章
|
19天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
28天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
35 0
|
8天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
23天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
42 1
Spring 框架:Java 开发者的春天
|
28天前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
35 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
13天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
26 1
|
15天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
15天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
65 1
|
23天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
29天前
|
人工智能 开发框架 Java
总计 30 万奖金,Spring AI Alibaba 应用框架挑战赛开赛
Spring AI Alibaba 应用框架挑战赛邀请广大开发者参与开源项目的共建,助力项目快速发展,掌握 AI 应用开发模式。大赛分为《支持 Spring AI Alibaba 应用可视化调试与追踪本地工具》和《基于 Flow 的 AI 编排机制设计与实现》两个赛道,总计 30 万奖金。