• Spring中Aop的理解


    Spring中的Aop

    1、什么是AOP?

    面向切面编程。利用它可以对业务逻辑的各个部分进行隔离,从而使得业务部分之间的耦合度降低,提高程序开发效率。

    应用场景有:日志记录、性能统计、安全控制、事务处理、异常处理...

     

    通俗描述:不通过修改源代码方式,在主干功能里添加新功能

     

    AOP底层原理:

    1、底层使用了动态代理

    (1)有两种情况的动态代理

    第一种:有接口,使用JDK动态代理

    (1)调用newProxyInstance方法

    方法三个参数:

    第一:类加载器

    第二:增强方法所在的类,这个类实现的接口,支持多个接口

    第三:实现这个接口InvocationHandler,创建代理对象,写增强方法,示例代码如下:

    public class ProxyJDK {
        public static void main(String[] args) {
            //创建接口实现类代理对象
            Class[] interfaces = {UserDao.class};
         /*   Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return null;
                }
            });*/
            UserDaoImpl userDao=new UserDaoImpl();
            UserDao dao = (UserDao) Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
            dao.update();
        }
    }
    
    
    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler {
        //创建的是谁的代理对象,把谁传过来,有参构造器
        private Object obj;
    
        public UserDaoProxy(Object obj) {
            this.obj = obj;
        }
    
        //增强部分
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //方法之前
            System.out.println("开始增强" + method.getName() + ":传递的参数.." + Arrays.toString(args));
            //被增强的方法执行
            Object invoke = method.invoke(obj, args);
            //方法之后
            System.out.println("执行结束" + obj);
    
            return null;
        }
    }

     

    创建接口实现类代理对象,增强类的方法

     

    第二种:没有接口情况,使用CGLIB动态代理

     

    创建子类的代理对象,增强类的方法

     

    AOP术语:

    1、连接点:类里哪些方法可以被增强,这些方法称为切入点

     

    2、切入点:实际被真正增强的方法

     

    3、通知(增强):实际增强的逻辑部分

    类型有:

    前置通知:

    后置通知:

    环绕通知:

    异常通知:

    最终通知:

     

    4、切面:是动作,把通知应用到切入点的过程

     

    AOP操作:

    1、一般基于AspectJ实现。

    2、基于AspectJ实现AOP操作:

    (1)基于xml配置文件

    (2)基于注解方式(常用)

    3、需要引入的依赖:

     

     其中aspectj.weaver包用下面的包代替:

     <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.7</version>
        </dependency>
    

      

     4、切入点表达式:

    (1)作用:知道对哪个类里的哪个方法进行增强

    (2):语法结构:

    execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))

    示例:对com.zhaojianhui.dao.Bookdao类里的add方法增强

    execution(* com.zhaojianhui.dao.Bookdao.add(..))

    示例:对com.zhaojianhui.dao.Bookdao类里的所有方法增强

    execution(* com.zhaojianhui.dao.Bookdao.*(..))

    示例:对com.zhaojianhui.dao包里所有类,类里的所有方法增强

    execution(* com.zhaojianhui.dao.*.*(..))

    AOP操作(注解方式)

    1、创建类,在类中定义方法

    public class User {
        public void add(){
            System.out.println("add...");
        }
    }
    

      2、创建增强类(编写增强逻辑)

    //增强类
    public class UserProxy {
        //前置通知
        public void before(){
            System.out.println("before..");
        }
    }
    

      3、通知配置

    (1)在spring配置文件中开启注解扫描

    <?xml version="1.0" encoding="utf-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:util="http://www.springframework.org/schema/util"
           xmlns:context="http://www.springframework.org/schema/context"
           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/util
             http://www.springframework.org/schema/util/spring-util.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">

      

    (2)使用注解创建User和UserProxy对象

    (3)在增强类上加注解@Aspect

    (4)在spring配置文件中开启生成代理对象

     <!--开启AspectJ代理生产对象-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    

      4、配置不同类型通知

    @Component
    @Aspect
    //增强类
    public class UserProxy {
        //前置通知
        @Before("execution(* org.zhaojianhui.Spring.Bean.User.add(..))")
        public void before(){
            System.out.println("before..");
        }
    }

    测试:

    public void test() {
            ApplicationContext appo = new ClassPathXmlApplicationContext("bean2.xml");
            //ApplicationContext appo = new AnnotationConfigApplicationContext(SpringConfig.class);;//加载配置类
            User user = appo.getBean("user", User.class);
            user.add();
    
    
        }
    }
    

      

    public class ProxyJDK {
    public static void main(String[] args) {
    //创建接口实现类代理对象
    Class[] interfaces = {UserDao.class};
    /* Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    return null;
    }
    });*/
    UserDaoImpl userDao=new UserDaoImpl();
    UserDao dao = (UserDao) Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
    dao.update();
    }
    }


    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler {
    //创建的是谁的代理对象,把谁传过来,有参构造器
    private Object obj;

    public UserDaoProxy(Object obj) {
    this.obj = obj;
    }

    //增强部分
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //方法之前
    System.out.println("开始增强" + method.getName() + ":传递的参数.." + Arrays.toString(args));
    //被增强的方法执行
    Object invoke = method.invoke(obj, args);
    //方法之后
    System.out.println("执行结束" + obj);

    return null;
    }
    }


    相同切入点抽取:
    //前置通知
        @Before(value = "pointCutDemo()")
        public void before() {
            System.out.println("before..");
        }
        //相同切入点抽取
        @Pointcut(value = "execution(* org.zhaojianhui.Spring.Bean.User.add(..))")
        public void pointCutDemo() {
    
        }

    有多个增强类对同一个方法进行增强,设置增强类优先级:在增强类上添加@Order(值)注解,值越小,优先级越高。



  • 相关阅读:
    [LeetCode] 330. Patching Array 数组补丁
    [LeetCode] 875. Koko Eating Bananas 可可吃香蕉
    [LeetCode] 460. LFU Cache 最近最不常用页面置换缓存器
    [LeetCode] 395. Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串
    [LeetCode] 29. Divide Two Integers 两数相除
    [LeetCode] 451. Sort Characters By Frequency 根据字符出现频率排序
    [LeetCode] 296. Best Meeting Point 最佳开会地点
    [LeetCode] 317. Shortest Distance from All Buildings 建筑物的最短距离
    css3动画4
    CSS Transform / Transition / Animation 属性的区别
  • 原文地址:https://www.cnblogs.com/zhaojianhui/p/13467393.html
Copyright © 2020-2023  润新知