Spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 BeanPostProcessor 来实现这项功能。

这三种自动代理创建器 为:BeanNameAutoProxyCreator     ,  DefaultAdvisorAutoProxyCreator  ,    AbstractAdvisorAutoProxyCreator。

1BeanPostProcessor

BeanPostProcessor 代理创建器的实现类可以分为 3 类:

类型 实现类
基于 Bean 配置名规则 BeanNameAutoProxyCreator
基于 Advisor 匹配规则 DefaultAdvisorAutoProxyCreator
基于 Bean 中的 AspectJ 注解标签的匹配规则 AnnotationAwareAspectJAutoProxyCreator

BeanPostProcessor 类继承关系

所有的自动代理器类都实现了 BeanPostPorcessor ,在容器实例化 Bean 时, BeanPostProcessor 将对它进行加工处理,所以自动代理创建器能够对满足匹配规则的 bean 自动创建代理对象。

2 BeanNameAutoProxyCreator

假设有以下两个实体类(用户与充电宝)。

用户类:

public class User {

    public void rent(String userId) {
System.out.println("User:租赁【充电宝】");
} public void back(String userId){
System.out.println("User:归还【充电宝】"); }
}

充电宝:

public class Charger {

    public void rent(String userId) {
System.out.println("Charger:【充电宝】被租赁");
}
}

我们希望通过 BeanNameAutoProxyCreator 通过 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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="user" class="net.deniro.spring4.aop.User"/>
<bean id="charger" class="net.deniro.spring4.aop.Charger"/> <!-- 前置增强-->
<bean id="rentBeforeAdvice" class="net.deniro.spring4.aop.RentBeforeAdvice"/> <!-- 使用 BeanNameAutoProxyCreator-->
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
p:beanNames="*er"
p:interceptorNames="rentBeforeAdvice"
p:optimize="true"
></bean>
</beans>

BeanNameAutoProxyCreator的 beanNames 属性允许指定一组需要自动代理的 Bean 名称, 这里可以使用 * 通配符 。

因为我们需要代理的类名分别是 user 与 charger,都是以 er 结尾的,所以我们这里定义为 *er

也可以通过 beanNames 的 value 值来明确指定需要代理的 Bean 名称,多个以逗号分隔(更常用)。

<!-- 指定自动代理的 Bean 名称-->
<property name="beanNames" value="user,charger">
</property>

也可以通过 list 方式来指定 beanNames 的值:

<property name="beanNames">
<list>
<value>user</value>
<value>charger</value>
</list>
</property>

p:optimize 设置为 true,则表示使用 CGLib 动态代理技术。

通过这样的配置之后,容器在创建 user 和 charger Bean 的实例时,就会自动为它们创建代理对象,而这一操作对于使用者来说完全是透明的 。

单元测试:

User user = (User) context.getBean("user");
Charger charger = (Charger) context.getBean("charger"); String userId = "001";
user.rent(userId);
charger.rent(userId);

输出结果:

准备租赁的用户 ID:001
User:租赁【充电宝】
准备租赁的用户 ID:001
Charger:【充电宝】被租赁

3 DefaultAdvisorAutoProxyCreator

切面 Advisor 是切点和增强的复合体,而 DefaultAdvisorAutoProxyCreator 能够扫描 Advisor, 并将 Advisor 自动织入到匹配的目标 Bean 中。

<bean id="user" class="net.deniro.spring4.aop.User"/>
<bean id="charger" class="net.deniro.spring4.aop.Charger"/> <!-- 前置增强-->
<bean id="rentBeforeAdvice" class="net.deniro.spring4.aop.RentBeforeAdvice"/> <!-- 静态正则表达式方法名匹配-->
<bean id="regexpAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:advice-ref="rentBeforeAdvice">
<!-- 匹配模式-->
<property name="patterns">
<list>
<!-- 匹配字符串-->
<value>.*rent.*</value>
</list>
</property>
</bean> <!-- 使用 DefaultAdvisorAutoProxyCreator-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

首先我们配置了以静态正则表达式方法名匹配的切面,然后直接配置了 DefaultAdvisorAutoProxyCreator Bean。

测试代码与输出结果与上一小节的 BeanNameAutoProxyCreator 相同。

JDK 动态代理是通过接口来实现方法拦截,所以必须确保要拦截的目标在接口中有定义。

CGLib 动态代理是通过动态生成代理子类来实现方法拦截,所以必须确保要拦截的目标方法可以被子类所访问,也就是目标方法必须定义为非 final, 且非私有实例方法 。

Spring 中如何自动创建代理(spring中的三种自动代理创建器)的更多相关文章

  1. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件

    精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件 内容简介:本文介绍 Spring Boot 的配置文件和配置管理,以及介绍了三种读取配置文 ...

  2. spring mvc从前台往后台传递参数的三种方式

     jsp页面: 第一种:使用控制器方法形参的方式(常用) 第二种:使用模型传参的方式(如果前台往后台传递的参数非常多,如果还使用形参的方式传递,非常复杂.我们可以使用模型传参的方式,把多 个请求的参数 ...

  3. ARM微处理器中支持字节、半字、字三种数据类型,地址的低两位为0是啥意思?

    问题: ARM微处理器中支持字节.半字.字三种数据类型,其中,字需要4字节对齐(地址的低两位为0).半字需要2字节对齐(地址的最低位为0).我想问的是括号中的内容是什么意思呢?请牛人帮忙解释一下!谢谢 ...

  4. Spring Boot将Mybatis返回结果转为驼峰的三种实现方式

    本文不再更新,可能存在内容过时的情况,实时更新请访问原地址:Spring Boot将Mybatis返回结果转为驼峰的三种实现方式: 我们通常获取Mybatis返回的数据结果时想要将字段以驼峰的形式返回 ...

  5. spring mvc从后台往前台传参数的三种方式

    第一种:使用Model对象(常用) 第一步:使用model对象往前台传递数据 第二步:在jsp中接收从后台传递过来的参数 第二种:使用HttpServletRequest对象 第一步:使用HttpSe ...

  6. CentOS7创建本地YUM源的三种方法

    这篇文章主要介绍了CentOS7创建本地YUM源的三种方法,本文讲解了使用CentOS光盘作为本地yum源.如何为CentOS创建公共镜像.创建完全自定义的本地源等内容,需要的朋友可以参考下     ...

  7. Windows 10 应用创建模糊背景窗口的三种方法

    原文 Windows 10 应用创建模糊背景窗口的三种方法 现代的操作系统中创建一张图片的高斯模糊效果非常容易,不过如果要在窗口中获得模糊支持就需要操作系统的原生支持了.iOS/Mac 和 Windo ...

  8. 02 Spring框架 简单配置和三种bean的创建方式

    整理了一下之前学习Spring框架时候的一点笔记.如有错误欢迎指正,不喜勿喷. 上一节学习了如何搭建SpringIOC的环境,下一步我们就来讨论一下如何利用ioc来管理对象和维护对象关系. <? ...

  9. Spring创建对象的三种方式以及创建时间

    创建对象的三种方式: 1.采用默认的构造函数创建 2.采用静态工厂方法 1.写一个静态工厂方法类 public class HelloWorldFactory { public static Hell ...

随机推荐

  1. Zookeeper集群快速搭建

    Zookeeper集群快速搭建 1.cd /usr/local/zookeeper/conf(如在192.168.212.101服务器) mv zoo_sample.cfg zoo.cfg 修改con ...

  2. Linux系统层级结构标准

    Linux Foundation有一套标准规范: FHS: Filesystem Hierarchy[‘haɪərɑːkɪ] Standard(文件系统层级标准)目前最新的标准是2.3版本:http: ...

  3. Mysql 查看连接数,状态及最大并发数(转载)

    -- show variables like '%max_connections%'; 查看最大连接数 set global max_connections=1000 重新设置   mysql> ...

  4. sudo 不用输入密码

    3. 设置当前登陆用户免密 使用visudo打开sudoers并编辑 sudo visudo 在刚才编辑的内容中加上NOPASSWD: linuxidc ALL=(ALL:ALL) NOPASSWD: ...

  5. mybatis 分页插件PageHelper的简单使用

    首先在pom.xml配置文件中增加相关的插件. 插件地址:https://github.com/pagehelper/Mybatis-PageHelper <dependency> < ...

  6. 红帽Linux故障定位技术详解与实例(2)

    红帽Linux故障定位技术详解与实例(2) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍 ...

  7. 求两个数的最大公约数和最小公倍数Java(cvte考题)

    //最大公约数 最小公倍数 通过测试 public class GongYue{ public static int gongyue(int m, int n) throws Exception{ i ...

  8. Python 面向对象Ⅴ

    基础重载方法 下表列出了一些通用的功能,你可以在自己的类重写: 运算符重载 Python同样支持运算符重载,实例如下: 以上代码执行结果如下所示: 类属性与方法 类的私有属性 __private_at ...

  9. json的值键对,对象,数组,逻辑值

    详细说一下有关json的相关知识: ㈠json与xml的异同 ★与 XML 相同之处 ⑴JSON 是纯文本 ⑵JSON 具有"自我描述性"(人类可读) ⑶JSON 具有层级结构(值 ...

  10. Tomcat 激活spring profile

    springboot打包war部署到外部tomcat的时候指定profile启动 windows 在%tomcat%/bin下创建setenv.bat文件 linux 在%tomcat%/bin下创建 ...