当前位置: 首页 > 编程笔记 >

Spring AOP拦截-三种方式实现自动代理详解

伍捷
2023-03-14
本文向大家介绍Spring AOP拦截-三种方式实现自动代理详解,包括了Spring AOP拦截-三种方式实现自动代理详解的使用技巧和注意事项,需要的朋友参考一下

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

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

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

用Spring一个自动代理类DefaultAdvisorAutoProxyCreator:

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

例如:

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

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

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

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

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

演示结果:

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

我们也可以写一个类,来实现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 class="cn.hncu.xmlImpl.Person" id="person"></bean>
 
  <!-- 切面 = 切点+通知 -->
  <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor">
    <!-- 切点 -->
    <property name="patterns">
      <list>
        <value>.*run.*</value>
      </list>
    </property>
    <!-- 通知-由我们写,实际代理动作 -->
    <property name="advice">
      <bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></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=https://www.springframework.org/schema/aop

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

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

我们需要一个aspectjweaver-jar包:

xml配置文件:

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

测试结果:

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

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

总结

以上本文关于Spring AOP拦截-三种方式实现自动代理详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:快速理解Java设计模式中的组合模式、Java编程接口调用的作用及代码分享、浅谈Java实体对象的三种状态以及转换关系等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!

 类似资料:
  • 本文向大家介绍Java两种方式实现动态代理,包括了Java两种方式实现动态代理的使用技巧和注意事项,需要的朋友参考一下 一、JDK动态代理 Java 在 java.lang.reflect 包中有自己的代理支持,该类(Proxy.java)用于动态生成代理类,只需传入目标接口、目标接口的类加载器以及 InvocationHandler 便可为目标接口生成代理类及代理对象。我们称这个Java技术为:

  • 本文向大家介绍PHP三种方式实现链式操作详解,包括了PHP三种方式实现链式操作详解的使用技巧和注意事项,需要的朋友参考一下 在php中有很多字符串函数,例如要先过滤字符串收尾的空格,再求出其长度,一般的写法是: 如果要实现类似js中的链式操作,比如像下面这样应该怎么写? 下面分别用三种方式来实现: 方法一、使用魔法函数__call结合call_user_func来实现 思想:首先定义一个字符串类S

  • 本文向大家介绍IOS 代理方式实现实例详解,包括了IOS 代理方式实现实例详解的使用技巧和注意事项,需要的朋友参考一下 IOS 代理方式实现 在客户端开发中,经常用到通知、代理、block来实现各个页面之间关联。通知,以一直“盲”的方式实现传递。 代理、block 可以很明确的知道各个界面之间的关联关系。以代理为例,一般的做法如下 : DesViewController *des = [[DesV

  • 本文向大家介绍详解三种C#实现数组反转方式,包括了详解三种C#实现数组反转方式的使用技巧和注意事项,需要的朋友参考一下 今天上班中午吃饱之后、逛博客溜达看到一道题:数组反转  晚上回家洗完澡没事情做,就自己练习一把。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 本文向大家介绍移动端点击态处理的三种实现方式,包括了移动端点击态处理的三种实现方式的使用技巧和注意事项,需要的朋友参考一下 前言 在开发移动端页面的时候,为了提高用户体验,通常会给被触控的元素加上一个效果来对用户的操作进行反馈。这种反馈主要有三种实现方式,有需要的朋友们下面来一起看看吧。 一、伪类:active :active伪类常用于设定点击状态下或其他被激活状态下一个链接的样式。最常用于锚点<

  • 本文向大家介绍PHP实现链式操作的三种方法详解,包括了PHP实现链式操作的三种方法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP实现链式操作的三种方法。分享给大家供大家参考,具体如下: 在php中有很多字符串函数,例如要先过滤字符串收尾的空格,再求出其长度,一般的写法是: 如果要实现类似js中的链式操作,比如像下面这样应该怎么写? 下面分别用三种方式来实现: 方法一、使用魔法函