zoukankan      html  css  js  c++  java
  • AOP 面向切面编程

    AOP学习

    AOP概述

      AOP(Aspect Oriented Programming)是面向切面编程,是OOP的扩展,可以解决OOP代码开发过程中遇到的问题。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    AOP的应用场景

      应用场景有很多,这里只列举一小部分

    • 打印操作日志,防止小伙伴删库跑路
    • 测试系统性能
    • 事务控制

    AOP和Spring AOP、AspectJ

    • AOP最早是AOP联盟提出的,并且制定规范
    • Spring AOP 遵循AOP规范,Spring AOP只能在Spring中使用
    • AspectJ是一个面向切面的框架,它扩展了Java语言,AspectJ定义了AOP语法。Aspect可以在Spring框架以及其他框架内使用

    AOP实现原理

    AOP实现是通过动态代理实现的

    • jdk动态代理: 对实现接口的类产生代理
    • cglib动态代理:对没有实现接口的类产生代理

    Spring底层如果类实现了接口用jdk动态代理,没有实现接口默认用CGLIB动态代理。当然这是默认的,如果需要也可以强制使用。当然这是后话了

      

    /**
     * JDK动态代理,利用反射完成
     */
    public class JdkProxy implements InvocationHandler {
        private Object target;
    
        public JdkProxy(Class target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object target, Method method, Object[] args) throws Throwable {
    
            System.out.println("===before===");
            Object obj = method.invoke(target, args);
            System.out.println("===after===");
            return obj;
        }
    
        public Object getProxy() {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                    this);
        }
    }
    JDK动态代理
    /**
     * Cglib动态代理,通过继承生成目标类的代理类
     */
    public class CglibProxy implements MethodInterceptor {
    
        private Object target;
        public CglibProxy(Object target) {
            this.target = target;
        }
        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            //方法前增强
            System.out.println("***before***");
            Object obj = methodProxy.invoke(proxy, args);
            //方法后增强
            System.out.println("***after****");
            return obj;
        }
    
        public Object getInstance() {
            //创建增强器
            Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(this.target.getClass());
            //设置回调
            enhancer.setCallback(this);
            //返回对象
            Object obj = enhancer.create();
            return obj;
        }
    }
    Cglib 动态代理
    Cglib动态代理,要记得引包
    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
    <dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.8</version>
    </dependency>

    AOP相关术语

    • Joincut :连接点,可以理解为被拦截的点
    • Pointcut: 切入点,实际上被拦截的点。因为项目中有许多能够被拦截的方法,我们只需根据需求拦截方法
    • Advice: 通知,也叫做增强,可以理解为对方法的增强。比如要在方法的前面增加业务逻辑
    • Introduction:引介,对类的增强,很少用。除非需要更改被代理类的内部属性
    • Weaving: 织入,把通知应用到目标对象的过程
    • Aspect: 切面,是多个通知和切入点的组合
    • Target: 目标对象
    • Proxy: 代理对象

    Spring中五种通知类型

    • @Before: 前置通知,在方法之前增强
    • @After: 后置通知,在方法之后增强
    • @AfterReturing: 后置返回通知,可以接收方法的返回值
    • @AfterThrowing: 异常抛出通知,方法有异常的时候执行
    • @Around: 环绕通知,可以在方法执行前和执行后进行增强。事务就是用@Around实现的

    Spring整合AOP

     github项目源码地址: https://github.com/AmberBar/Learning/tree/master/SpringAOP

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>groupId</groupId>
        <artifactId>SpringAOP</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>4.3.10.RELEASE</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>4.0.8.RELEASE</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>4.0.8.RELEASE</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.8.2</version>
                <!--<scope>test</scope>-->
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>4.0.8.RELEASE</version>
                <scope>test</scope>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/cglib/cglib -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.8</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.1</version>
            </dependency>
    
        </dependencies>
    </project>
    pom.xml
    package com.amber.dao;
    
    public interface ProductDao {
    
        void create();
    
        void delete();
    
        String update();
    
        void addBatch();
    
        void delBatch();
    }
    ProductDao
    package com.amber.dao;
    
    public class ProduceDaoImpl implements ProductDao {
    
        @Override
        public void create() {
            System.out.println("=========this is create method ==============");
        }
    
        @Override
        public void delete() {
            System.out.println("=========this is delete method ==============");
        }
    
        @Override
        public String update() {
            System.out.println("=========this is update method ==============");
            return "amber";
        }
    
        @Override
        public void addBatch() {
            System.out.println("=========this is addBatch method ==============");
        }
    
        @Override
        public void delBatch() {
            System.out.println("=========this is delBatch method ==============");
            int i = 1/0;
        }
    }
    ProduceDaoImpl 

    基于Xml的形式

    <?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.xsd">
    
        <!--配置扫描-->
        <context:component-scan base-package="com.amber"> </context:component-scan>
        <bean id="userDao" class="com.amber.dao.ProduceDaoImpl"></bean>
        <bean id="aspectOption" class="com.amber.aspect.AspectOption"></bean>
    
        <!--xml aop配置-->
        <aop:config>
            <!--设置切入点-->
            <aop:pointcut id="create" expression="execution(* com.amber.dao.ProductDao.create(..))" ></aop:pointcut>
            <aop:pointcut id="delete" expression="execution(* com.amber.dao.ProductDao.delete(..))" ></aop:pointcut>
            <aop:pointcut id="delBatch" expression="execution(* com.amber.dao.ProductDao.delBatch(..))" ></aop:pointcut>
            <aop:pointcut id="addBatch" expression="execution(* com.amber.dao.ProductDao.addBatch(..))" ></aop:pointcut>
            <aop:pointcut id="update" expression="execution(* com.amber.dao.ProductDao.update(..))" ></aop:pointcut>
            <!--设置切面类-->
            <aop:aspect ref="aspectOption">
                <!--设置前置通知-->
                <aop:before method="before" pointcut-ref="create"></aop:before>
                <!--设置后置通知-->
                <aop:after method="after" pointcut-ref="delete"></aop:after>
                <!--环绕通知-->
                <aop:around method="around" pointcut-ref="addBatch"></aop:around>
                <!--设置后置返回通知-->
                <aop:after-returning method="afterReturning" pointcut-ref="update" returning="result"></aop:after-returning>
                <!--设置后置异常通知-->
                <aop:after-throwing method="afterThrowing" pointcut-ref="delBatch" throwing="e"></aop:after-throwing>
            </aop:aspect>
        </aop:config>
    </beans>
    applicationContext_xml.xml
    package com.amber.xml;
    
    import com.amber.dao.ProductDao;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext_xml.xml")
    public class ProductDaoTest {
    
        @Autowired
        ProductDao productDao;
    
        @Test
        public void beforeTest() {
            productDao.create();
        }
    
        @Test
        public void afterTest() {
            productDao.delete();
        }
    
        @Test
        public void afterReturingTest() {
            productDao.update();
        }
    
        @Test
        public void aroundTest() {
            productDao.addBatch();
        }
    
        @Test
        public void delBatchTest() {
            productDao.delBatch();
        }
    
    }
    测试

    基于注解形式

    package com.amber.xml;
    
    import com.amber.dao.ProductDao;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext_xml.xml")
    public class ProductDaoTest {
    
        @Autowired
        ProductDao productDao;
    
        @Test
        public void beforeTest() {
            productDao.create();
        }
    
        @Test
        public void afterTest() {
            productDao.delete();
        }
    
        @Test
        public void afterReturingTest() {
            productDao.update();
        }
    
        @Test
        public void aroundTest() {
            productDao.addBatch();
        }
    
        @Test
        public void delBatchTest() {
            productDao.delBatch();
        }
    
    }
    测试
    <?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.xsd">
    
        <!--配置扫描-->
        <context:component-scan base-package="com.amber"> </context:component-scan>
        <bean id="userDao" class="com.amber.dao.ProduceDaoImpl"></bean>
        <bean id="aspectOption" class="com.amber.aspect.AspectOption"></bean>
    
        <!--配置注解代理-->
        <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
    </beans>
    ApplicationContext.xml
    package com.amber.xml.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    
    /**
     * 基于注解
     */
    @Aspect
    public class AspectOption {
    
        /**
         * 前置增强,在方法之前执行
         */
    
        public void before() {
            System.out.println("AspectOption before");
        }
    
        /**
         * 后置增强,在方法执行之后执行
         */
    
        public void after() {
            System.out.println("AspectOption after");
        }
    
        /**
         * 后置通知增强,可以获取到方法的返回值
         * @param result
         */
    
        public void afterReturning(String result) {
            System.out.println("AspectOption afterReturning " + result);
        }
    
        /**
         * 环绕通知,在方法执行之前和执行之后运行
         * @param joinPoint
         */
    
        public void around(ProceedingJoinPoint joinPoint) {
            System.out.println("AspectOption around before");
            try {
                Object obj = joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.println("AspectOption around after");
        }
    
        /**
         * 异常抛出通知,方法抛出异常的时候执行
         * @param e
         */
    
        public void afterReturing(Throwable e) {
            System.out.println("AspectOption afterReturing");
            System.out.println(e);
        }
    }
    AspectOption
  • 相关阅读:
    URAL 1998 The old Padawan 二分
    URAL 1997 Those are not the droids you're looking for 二分图最大匹配
    URAL 1995 Illegal spices 贪心构造
    URAL 1993 This cheeseburger you don't need 模拟题
    URAL 1992 CVS
    URAL 1991 The battle near the swamp 水题
    Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力
    Codeforces Beta Round #7 D. Palindrome Degree hash
    Codeforces Beta Round #7 C. Line Exgcd
    Codeforces Beta Round #7 B. Memory Manager 模拟题
  • 原文地址:https://www.cnblogs.com/amberbar/p/9763941.html
Copyright © 2011-2022 走看看