美文网首页程序员Java 杂谈Spring AOP
说说在 Spring 中如何自动创建代理

说说在 Spring 中如何自动创建代理

作者: deniro | 来源:发表于2018-06-19 16:07 被阅读560次

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

1 BeanPostProcessor

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 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 B...

  • spring-AOP(二) 自动代理

    spring-AOP(二) 自动代理 知识导读 在何时何处创建代理对象,如何能覆盖被代理对象,返回代理后的对象 自...

  • Spring AOP 自动创建代理

    1. 代理创建器 自动创建代理对象,将一个切面织入到多个目标对象中 三种自动代理创建器BeanNameAutoPr...

  • 说说在 Spring 中如何创建切面(AOP)

    Spring 的增强提供了连接点的方位信息(织入方法前、方法后等),而切点则描述了增强需要织入到哪个类的哪一个方法...

  • Spring注解--AOP原理(五):代理对象目标方法的执行

    在前面的章节中,谈到代理对象的创建:参考Spring注解--AOP原理(四):业务bean与代理bean的创建, ...

  • Spring 创建Bean的6种方式

    前言 本文讲解了在Spring 应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根...

  • service调用过程分析

    测试代码: 在创建bean时,spring通过jdk动态代理为StockService创建动态代理类,上图为运行时...

  • spring aop半自动与全自动编程

    在spring中,我们可以通过在配置文件中配置目标类,切面类,代理类来达到目的。首先要讲的的是半自动代理。这种情况...

  • AOP代理:

    AOP代理:AOP框架创建的对象,代理就是对目标对象的增强。Spring中的AOP代理可以是JDK动态代理,也可以...

  • Spring自动代理

    Spring自动代理 Spring的一般代理是通过ProxyFactoryBean织入切面代理,如果有非常多的Da...

网友评论

    本文标题:说说在 Spring 中如何自动创建代理

    本文链接:https://www.haomeiwen.com/subject/pxbaeftx.html