zoukankan      html  css  js  c++  java
  • Spring AOP增强与使用

    1.AOP增强有几种类型?

    前置通知(在目标方法执行前增强)
    后置通知(在目标方法执行后增强)
    环绕通知(在目标方法执行前和执行后都增强)
    异常通知(发生异常时增强)
    引介通知(不用了解)

    2.Spring AOP切面有几种类型?

    Advisor:代表一般切面,即对一个类的所有方法都增强
    PointcutAdvisor:代表具有切点的切面,可以是一个或者多个方法增强
    IntroductionAdvisor:代表引介切面,针对引介通知而使用切面
    

    ShowTime:让我们来实验一下这三种通知在一般切面上的应用吧

    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class MyAdviceBefore implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println("前置通知");
        }
    }
    
    
    import org.springframework.aop.AfterReturningAdvice;
    
    import java.lang.reflect.Method;
    
    public class MyAdviceAfter implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
            System.out.println("后置通知");
        }
    }
    
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class MyRoundAdvice implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            System.out.println("执行前置操作");
            Object object=methodInvocation.proceed();
            System.out.println("执行后置操作");
            return object;
        }
    }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
        <!--配置前置操作-->
        <bean id="product" class="com.ibuyi.free.spring.Product"/>
        <bean id="myadvicebefore" class="com.ibuyi.free.spring.MyAdviceBefore"/>
        <bean id="myadviceafter" class="com.ibuyi.free.spring.MyAdviceAfter"/>
        <bean id="myroundadvice" class="com.ibuyi.free.spring.MyRoundAdvice"/>
        <bean id="productproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="product"/>
            <!--是否对类代理而不是接口,设置为true时,使用CGlib产生代理-->
            <property name="proxyTargetClass" value="true"/>
             <!--强制使用CGlib产生代理-->
            <property name="optimize" value="true"/>
            <!--不同的通知类型只需要把interceptNames改为对应的通知即可-->
            <property name="interceptorNames" value="myroundadvice"/>
        </bean>
    </beans>
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resource;
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class iTest {
        @Resource(name = "productproxy")
        Product product;
        @Test
        public void demo1(){
           product.delete();
           product.find();
           product.save();
           product.update();
        }
    }
    
    
    public class Product {
        public void save(){
            System.out.println("保存操作");
        }
    
        public void delete(){
            System.out.println("删除操作");
        }
    
        public void update(){
            System.out.println("更新操作");
        }
    
        public void find(){
            System.out.println("查询操作");
        }
    }
    
    

    实验结果
    1.前置通知
    在这里插入图片描述
    2.后置通知在这里插入图片描述
    3.环绕通知在这里插入图片描述

    一般切面小结:采用proxyBeanFactory产生代理,会在对象的所有方法执行前后执行相应操作。其中环绕通知功能最强大,可以根据需要阻止原有逻辑的执行。





    下面,让我们继续了解Spring aop自动代理如何配置,在上面的实现过程中,如果我们要为很多类创建代理,那么就要在配置文件中配置很多bean,下面我们学习两种自动代理,减少不必要的配置代码。

    第一种,基于bean名称来自动配置
    BeanNameAutoProxyCreator:根据Bean名称创建代理

    public class ProductDAO {
        public void insert(){
            System.out.println("插入商品");
        }
        public void find(){
            System.out.println("查询商品");
        }
    }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
        <!--配置前置操作-->
        <bean id="product" class="com.ibuyi.free.spring.Product"/>
        <bean id="productdao" class="com.ibuyi.free.spring.ProductDAO"/>
        <bean id="myadvicebefore" class="com.ibuyi.free.spring.MyAdviceBefore"/>
        <bean id="myadviceafter" class="com.ibuyi.free.spring.MyAdviceAfter"/>
        <bean id="myroundadvice" class="com.ibuyi.free.spring.MyRoundAdvice"/>
        <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <!--这里使用beanNames,指定代理beanname以product开头的bean-->
               <property name="beanNames" value="product*"/>
               <property name="interceptorNames" value="myadvicebefore"/>
        </bean>
    </beans>
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resource;
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class iTest {
        @Resource(name = "product")
        Product product;
        @Resource(name = "productdao")
        ProductDAO productDAO;
        @Test
        public void demo1(){
           product.delete();
           product.find();
           product.save();
           product.update();
           productDAO.find();
           productDAO.insert();
        }
    }
    
    

    实验结果:
    在这里插入图片描述

    不过上面的通过bean名称自动创建代理的方法仍然存在不足,比如现在我想指定代理product中的某个方法,就没有办法实现,我们再引入第二种基于切面自动创建代理的方法。

    <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="pattern" value="com.ibuyi.free.spring.Product.save"/>
            <property name="advice" ref="myroundadvice"/>
        </bean>
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
    
  • 相关阅读:
    AOP入门之静态代理
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
    C# 6 与 .NET Core 1.0 高级编程
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13309414.html
Copyright © 2011-2022 走看看