Spring 自动代理创建器详细介绍及简单实例

Spring 自动代理创建器详细介绍及简单实例

什么是自动代理创建器

自动代理创建器(Automatic Proxy Creator)是 Spring 框架提供的一种自动创建代理对象的机制。自动代理创建器可以根据配置和规则自动地生成代理对象并加入 Spring 容器,简化了程序员手动创建代理对象的工作。

自动代理的配置方式

Spring 提供了多种方式来配置自动代理:

  1. 基于 BeanNameAutoProxyCreator 的配置方式
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
        <value>serviceName1*,serviceName2*</value>
    </property>
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
</bean>
  1. 基于 DefaultAdvisorAutoProxyCreator 的配置方式
<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
    <property name="proxyTargetClass" value="true"/>
</bean>

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"/>

<bean id="transactionAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
    <property name="pointcut">
        <bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
            <property name="patterns">
                <list>
                    <value>com.example.*.service.impl.*</value>
                </list>
            </property>
        </bean>
    </property>
    <property name="advice">
        <ref bean="transactionInterceptor"/>
    </property>
</bean>

示例

示例1:基于 BeanNameAutoProxyCreator 的自动代理

假设我们有一个 UserService 的接口和其实现类 UserServiceImpl,我们需要为 UserServiceImpl 提供一个事务拦截器进行事务管理,可以使用 BeanNameAutoProxyCreator 进行自动代理。

  1. 创建 UserService 接口和 UserServiceImpl 实现类

UserService 接口:

public interface UserService {

    User addUser(User user);

    User getUserById(Long userId);

}

UserServiceImpl 实现类:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional
    public User addUser(User user) {
        userMapper.save(user);
        return user;
    }

    @Override
    public User getUserById(Long userId) {
        return userMapper.findById(userId);
    }

}

其中 UserMapper 是一个 DAO 类,用于数据库操作。

  1. 创建事务拦截器 TransactionInterceptor
public class CustomTransactionInterceptor extends TransactionInterceptor {

    public CustomTransactionInterceptor(PlatformTransactionManager transactionManager, TransactionAttributeSource transactionAttributeSource) {
        super.setTransactionManager(transactionManager);
        super.setTransactionAttributeSource(transactionAttributeSource);
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        TransactionInfo transInfo = createTransactionIfNecessary(getTransactionAttributeSource(), invocation.getMethod(), invocation.getThis().getClass());
        Object result = null;
        try {
            result = invocation.proceed();
        } catch (Exception ex) {
            completeTransactionAfterThrowing(transInfo, ex);
            throw ex;
        } finally {
            cleanupTransactionInfo(transInfo);
        }
        commitTransactionAfterReturning(transInfo);
        return result;
    }
}
  1. 创建 BeanNameAutoProxyCreator 配置
<bean name="userService" class="com.example.service.impl.UserServiceImpl"/>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

<bean id="transactionInterceptor" class="com.example.aop.CustomTransactionInterceptor">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributeSource">
        <bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>
    </property>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
        <value>userService</value>
    </property>
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
</bean>

通过配置 BeanNameAutoProxyCreator,当 Spring 容器中有名为 userService 的 Bean 被创建时,会自动为其创建代理对象并添加事务拦截器。在实际使用中,我们可以在控制器中直接引用 userService Bean,无需再手动创建此 Bean 的代理对象。

示例2:基于 DefaultAdvisorAutoProxyCreator 的自动代理

假设我们有一个 OrderService 的接口和其实现类 OrderServiceImpl,我们需要为 OrderServiceImpl 提供一个日志拦截器进行日志记录,可以使用 DefaultAdvisorAutoProxyCreator 进行自动代理。

  1. 创建 OrderService 接口和 OrderServiceImpl 实现类

OrderService 接口:

public interface OrderService {

    Order addOrder(Order order);

    Order getOrderById(Long orderId);

}

OrderServiceImpl 实现类:

@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderMapper orderMapper;

    @Override
    public Order addOrder(Order order) {
        logger.info("Add order start: {}", order);
        orderMapper.save(order);
        logger.info("Add order end: {}", order);
        return order;
    }

    @Override
    public Order getOrderById(Long orderId) {
        return orderMapper.findById(orderId);
    }

}

其中 OrderMapper 是一个 DAO 类,用于数据库操作。

  1. 创建日志拦截器 LoggingInterceptor
public class LoggingInterceptor implements MethodInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        String className = invocation.getThis().getClass().getName();
        String methodName = invocation.getMethod().getName();
        Object[] args = invocation.getArguments();

        logger.info("entering method {}.{}", className, methodName);
        logger.info("arguments: {}", Arrays.toString(args));

        Object result = invocation.proceed();

        logger.info("returning from method {}.{}", className, methodName);
        logger.info("result: {}", result);

        return result;
    }
}
  1. 创建 DefaultAdvisorAutoProxyCreator 配置
<bean name="orderService" class="com.example.service.impl.OrderServiceImpl"/>

<bean id="loggingInterceptor" class="com.example.aop.LoggingInterceptor"/>

<bean id="loggingAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
    <property name="pointcut">
        <bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
            <property name="patterns">
                <list>
                    <value>com.example.*.service.impl.*</value>
                </list>
            </property>
        </bean>
    </property>
    <property name="advice">
        <ref bean="loggingInterceptor"/>
    </property>
</bean>

<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
    <property name="proxyTargetClass" value="true"/>
</bean>

通过配置 DefaultAdvisorAutoProxyCreator,当 Spring 容器中有包名为 com.example..service.impl. 的 Bean 被创建时,会自动为其创建代理对象并添加日志拦截器。在实际使用中,我们可以在控制器中直接引用 orderService Bean,无需再手动创建此 Bean 的代理对象。

结论

自动代理创建器是 Spring 框架提供的一个非常实用的机制,可以帮助开发者大大简化代码。需要注意的是,在使用时需要根据业务需求进行合理的配置,一般情况下应该将其作为辅助手段,而不是过度依赖。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring 自动代理创建器详细介绍及简单实例 - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • synchronized关键字如何保证线程安全?

    synchronized 关键字可以保证多线程环境下的线程安全。它可以用于修饰方法和代码块。 修饰方法 当一个 synchronized 关键字修饰的方法被一个线程调用时,该方法就会被锁定,以保证同一时间只有一个线程可以执行该方法,直到该方法执行完毕释放锁。下面是一个例子: public class ThreadSafeDemo { private int …

    Java 2023年5月10日
    00
  • jquery中的ajax异步上传

    下面是关于jQuery中的Ajax异步上传的完整攻略: 什么是Ajax异步上传 在之前不使用Ajax时,文件上传只能通过表单提交的方式,整个页面都要刷新。而现在采用Ajax提交方式,在页面不重载的情况下,上传文件并得到服务器端的响应。 异步上传的详细实现步骤: 设置一个表单,包含一个文件上传控件 <form action="your-url&…

    Java 2023年5月20日
    00
  • java中读写Properties属性文件公用方法详解

    Java中读写Properties属性文件公用方法详解 什么是Properties属性文件? Properties属性文件是Java中常用的一种配置文件,使用键值对的形式来保存配置数据。通常我们将应用程序中需要用户自行配置的数据以及程序运行时需要用到的配置数据都存储在Properties属性文件中进行统一管理。这种文件通常采用.properties扩展名。 …

    Java 2023年6月15日
    00
  • Java swing实现支持录音等功能的钢琴程序

    如何实现Java Swing支持录音等功能的钢琴程序? 导入所需库文件 实现这个功能的Java库有很多,我们可以使用Java Sound API、Java Media Framework、JLGui和JLayer。为了方便起见,我们在这里使用Java Sound API来实现这个功能。我们需要导入下面的库文件: <dependency> <…

    Java 2023年5月23日
    00
  • 线上问题排查回答(转载)

    面试官:「你是怎么定位线上问题的?」 这个面试题我在两年社招的时候遇到过,前几天面试也遇到了。我觉得我每一次都答得中规中矩,今天来梳理复盘下,下次又被问到的时候希望可以答得更好。 下一次我应该会按照这个思路去答: 1、如果线上出现了问题,我们更多的是希望由监控告警发现我们出了线上问题,而不是等到业务侧反馈。所以,我们需要对核心接口做好监控告警的功能。 2、如…

    Java 2023年4月27日
    00
  • java.lang.String和java.util.NClob互相转换方式

    在Java中,Java.lang.String类和Java.util.NClob类都是字符串类。但是,NClob是用于处理CLOB(字符大对象)的类,而String类则是用于处理字符串的类。如果需要将它们互相转换,需要进行一些特殊的步骤和技巧。下面是将Java.lang.String和Java.util.NClob类互相转换的完整攻略。 将String转换为…

    Java 2023年5月27日
    00
  • springboot整合多数据源配置方式

    对于“springboot整合多数据源配置方式的完整攻略”,我会逐步进行讲解。 1. 配置数据源 在项目中引入所需的依赖,例如: <!– JDBC驱动依赖,根据数据库不同而变化 –> <dependency> <groupId>com.mysql.jdbc</groupId> <artifactId&…

    Java 2023年5月20日
    00
  • SpringMVC对自定义controller入参预处理方式

    下面是关于“SpringMVC对自定义controller入参预处理方式”的完整攻略,包含两个示例说明。 SpringMVC对自定义controller入参预处理方式 SpringMVC是一个流行的Java Web框架,它可以帮助我们更加方便地构建Web应用程序。在SpringMVC中,我们可以使用自定义控制器来处理Web请求。本文将介绍如何使用Spring…

    Java 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部