zoukankan      html  css  js  c++  java
  • Spring

    1. 介绍

    AOP就是面向切面编程,简单说就是,在你执行别人的代码中坚插入你想执行的代码,在日常生活中,代理(中介)就是这么一个角色,先看看生活的例子,

    在没有代理之前:你现在需要去澳洲旅行,所以你需要买机票,但你不知道那个航空公司比较便宜,甚至那天买会比较便宜,如果你每天都上网查询机票价格,你会觉得很浪费时间,这个时候,你就需要一个代理,帮你完成看机票这么繁琐的事情

    有了代理之后:你只需要关注,买完机票之后所做的事情,例如订酒店。买机票这个动作你就交给你的代理去完成就好了

    根据上面的这个例子,我们这里就可以看看代码的实现了,我们会分3个方式来看

    • 原始JDK实现
    • gclib实现
    • spring实现
      • 半自动
      • 全自动

    2.最原始的JDK做法

    在这个列子中,就是不适用spring实现,这个是一个工厂类,使用者只需要执行这个createUserService的方法,就可以获取UserService的接口,然后执行所需要要的业务

    工厂类

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class MyBeanFacotry {
    
        public static UserService createUserService() {
            /**
             * 1. 创建目标对象
             */
            final UserService userService = new UserServiceImpl();
            
            /**
             * 2. 创建切面对象
             */
            final MyAspect myAspect = new MyAspect();
            
            /**
             * 3. 整合目标对象 和 切面对象
             * 所以需要使用JDK的动态代理,创建代理对象
             */
            UserService proxyUserService = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),UserServiceImpl.class.getInterfaces(),new InvocationHandler() {
                
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //执行切面的before方法
                    myAspect.beforeInvokeTarget();
                    
                    Object obj = method.invoke(userService, args);
                    
                    //执行切面的after方法
                    myAspect.afterInvokeTarget();
                    
                    return obj;
                }
            });
            
            return proxyUserService;
        }
    }

    测试类

    import org.junit.Test;
    
    public class TestAOP {
    
        @Test
        public void test() {
            UserService userService = MyBeanFacotry.createUserService();
            userService.addUser();
        }
    }

    3. 通过cgLib实现

    这里需要引用cglib的Jar包,但是spring-core的jar包里面已经引用了,所以这里就不需要引入了,测试类跟2的一样就可以,只需要改动一个工厂类就行

    public class MyBeanFacotry {public static UserService createUserService() {
            /**
             * 1. 创建目标对象
             */
            final UserService userService = new UserServiceImpl();
            
            /**
             * 2. 创建切面对象
             */
            final MyAspect myAspect = new MyAspect();
            
            /**
             * 3. 整合目标对象 和 切面对象
             * 这里使用cglib创建代理对象
             */
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(userService.getClass());
            
            enhancer.setCallback(new MethodInterceptor() {
                
                public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
                    Object obj = arg1.invoke(userService, arg2);
                    return obj;
                }
            });
            UserService proxyUserService = (UserService)enhancer.create();
            
            return proxyUserService;
        }
    }

    4. 接下来就是用apache的AOP

    跟上面两个方法不同是,这里只需要配置xml,这里需要使用到aopalliance-x.x.jar包和aspectjweaver-x.x.x.jar

    接口和实现类跟上面一样,这里就不重复写了,这里只写2个类和一个配置文件

    切面类

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class MyAspect implements MethodInterceptor {
    
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("切入前");
            
            Object obj = invocation.proceed();
            
            System.out.println("切入后");
            
            return obj;
        }
    
    }

    配置文件

    稍微讲解一下aop:config节点

    其中pointcut 是切入点,expression是表达式,id是切入点ID,主要通知引用

    advisor是通知,advice-ref就是指向切面类的bean,pointcut-ref就指向切入点的id

    <?xml version="1.0" encoding="UTF-8" ?>
    <beans   xmlns="http://www.springframework.org/schema/beans" 
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:aop="http://www.springframework.org/schema/aop"
             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
                                  http://www.springframework.org/schema/aop
                                  http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
            
            
            <bean id="userService" class="com.test.spring.aop.b.UserServiceImpl"></bean>
            
            <bean id="myAspect" class="com.test.spring.aop.b.MyAspect"></bean>
            
            <aop:config>
                <aop:pointcut expression="execution(* com.test.spring.aop.b.UserServiceImpl.deleteUser(..))" id="myCutPoint"/>
                <aop:advisor advice-ref="myAspect" pointcut-ref="myCutPoint"/>
            </aop:config>
         
    </beans>

    测试类

    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class SpringAOPTest {
    
        @Test
        public void test() {
            String configPath = new String("com/test/spring/aop/b/springConfig.xml");
            
            ApplicationContext context = new ClassPathXmlApplicationContext(configPath);
            UserService userService = context.getBean("userService",UserService.class);
            userService.addUser();
        }
    }

    总结,后面的章节将会讲解一下AspectJ

  • 相关阅读:
    How a webpage is loaded and displayed
    Tree知识总结
    Install Cassandra Locally
    axios接口封装
    Jsonp解决跨域问题
    react使用swiper,解决添加点击事件首位图片点击失效,解决轮播按钮被覆盖问题
    vue 生产环境和测试环境的配置
    vue使用远程在线更新代码
    vue.js axios实现跨域http请求接口
    leetcode每日一题(2020-05-27):974. 和可被 K 整除的子数组
  • 原文地址:https://www.cnblogs.com/oscar1987121/p/10879971.html
Copyright © 2011-2022 走看看