zoukankan      html  css  js  c++  java
  • SpringAOP

    SpringAOP

    AOP:Aspect Oriented Programming,意思为面向切面编程

    面向切面编程:对于不同的模块,在具有相同共性的情况下,由切面的增强来负责统一处理;其本质就是动态代理

    相对于OOP(面向对象)来说,AOP对于过程的管理更加的精细,能够进一步来完成解耦工作,在程序运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想,将不同的方法的同一个位置抽象成一个切面对象

    AOP的特点:

    • 降低模块之间的耦合度。

    • 使系统更容易扩展。

    • 更好的代码复用。

    • 非业务代码更加集中,不分散,便于统一管理。

    • 业务代码更加简洁纯粹,不参杂其他代码的影响。

    AOP相关术语:

    • 增强(Advice)
    • 切入点(Pointcut)
    • 连接点(Joinpoint)
    • 切面(Aspect)
    • 代理(Proxy)
    • 目标对象(Target)
    • 织入(Weaving)

    动态代理

    场景:苹果手机与苹果电脑,华为手机与华为电脑的销售

    接口:

    package com.m.staticproxy;
    
    public interface Phone {
        public String salePhone();
    }
    
    
    package com.m.staticproxy;
    
    public interface Computer {
        public String saleComputer();
    }
    
    

    实现类:

    package com.m.staticproxy.impl;
    
    import com.m.staticproxy.Computer;
    import com.m.staticproxy.Phone;
    
    public class Apple implements Phone,Computer {
        @Override
        public String salePhone() {
            return "销售Apple手机";
        }
    
        @Override
        public String saleComputer() {
            return "销售Apple电脑";
        }
    }
    
    
    package com.m.staticproxy.impl;
    
    import com.m.staticproxy.Computer;
    import com.m.staticproxy.Phone;
    
    public class HuaWei implements Phone,Computer {
        @Override
        public String salePhone() {
            return "销售HuaWei手机";
        }
    
        @Override
        public String saleComputer() {
            return "销售HuaWei电脑";
        }
    }
    
    

    MyInvocationHandler类:

    package com.m.staticproxy.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    public class MyInvocationHandler implements InvocationHandler {
        private Object proObject;
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Object bind(Object object) {
            this.proObject = object;
            return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
    }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = method.invoke(this.proObject);
            System.out.println(name+"卖的好,这个"+name+"物美价廉,赶快来抢购吧!");
            System.out.println(result);
            System.out.println(method.getName()+"方法的结果是"+result);
            return result;
        }
    }
    
    

    测试类:

    package com.m.staticproxy;
    
    import com.m.staticproxy.Phone;
    import com.m.staticproxy.impl.Apple;
    import com.m.staticproxy.impl.HuaWei;
    import com.m.staticproxy.proxy.MyInvocationHandler;
    import com.m.staticproxy.proxy.PhoneProxy;
    
    public class Test {
        public static void main(String[] args) {
            Phone phone1 = new Apple();
    
            Phone phone2 = new HuaWei();
    
            Computer computer1 = new Apple();
    
            Computer computer2 = new HuaWei();
    
            MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
    
            myInvocationHandler.setName(phone1.salePhone().substring(2));
            phone1 = (Phone) myInvocationHandler.bind(phone1);
            phone1.salePhone();
    
            myInvocationHandler.setName(phone2.salePhone().substring(2));
            phone2 = (Phone) myInvocationHandler.bind(phone2);
            phone2.salePhone();
    
            myInvocationHandler.setName(computer1.saleComputer().substring(2));
            computer1 = (Computer) myInvocationHandler.bind(computer1);
            computer1.saleComputer();
    
            myInvocationHandler.setName(computer2.saleComputer().substring(2));
            computer2 = (Computer) myInvocationHandler.bind(computer2);
            computer2.saleComputer();
    
        }
    }
    
    

    用静态代理得写手机代理类和电脑代理类,动态代理用的是多态思想,一个类搞定。

    Spring-aop

    在Spring框架中,我们不需要创建动态代理类,只需要创建一个切面类,由该切面类产生的对象就是切面对象,可以将非业务代码写入到切面对象中,再切入到业务方法中,Spring框架底层会自动根据切面类以及目标类生成一个代理对象。

    1.配置pom环境

        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>5.2.8.RELEASE</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>5.2.8.RELEASE</version>
        </dependency>
    

    2.spring-aop.xml

    <?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:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    	http://www.springframework.org/schema/aop
    	http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context-4.3.xsd
    ">
    
        <!-- 自动扫码 -->
        <context:component-scan base-package="com.m"></context:component-scan>
    
        <!-- 使Aspect注解生效,为委托类自动生成代理对象 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    </beans>
    

    目标类需要添加@Component注解

    package com.m.action_proxy.impl;
    
    import com.m.action_proxy.Cal;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CalImpl implements Cal {
        @Override
        public int add(int num1, int num2) {
            return num1 + num2;
        }
    
        @Override
        public int sub(int num1, int num2) {
            return num1 - num2;
        }
    
        @Override
        public int mul(int num1, int num2) {
            return num1 * num2;
        }
    
        @Override
        public int div(int num1, int num2) {
            return num1 / num2;
        }
    }
    
    

    LoggerAspect类定义处添加了两个注解:

    • @Aspect:表示该类是切面类。
    • @Component:将该类注入到IoC容器中。

    3.创建LoggerAspect类

    package com.m.aop;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    
    @Aspect
    @Component
    public class LoggerAspect {
    
        @Before(value = "execution(public int com.m.action_proxy.impl.CalImpl.*(..))")
        public void before(JoinPoint joinPoint){
            //获取方法名
            String name = joinPoint.getSignature().getName();
            //获取参数列表
            String args = Arrays.toString(joinPoint.getArgs());
            System.out.println(name+"的参数是:"+args);
        }
    
    
        @After("execution(public int com.m.action_proxy.impl.CalImpl.*(..))")
        public void after(JoinPoint joinPoint){
            //获取方法名
            String name = joinPoint.getSignature().getName();
            System.out.println(name+"方法结束");
           
        }
    
        @AfterReturning(value = "execution(public int com.m.action_proxy.impl.CalImpl.*(..)))",returning = "result")
        public void afterReturning(JoinPoint joinPoint,Object result){
            //获取方法名
            String name = joinPoint.getSignature().getName();
            System.out.println(name+"方法的结果是:"+result);
            System.out.println("---------------------------------");
        }
    
        @AfterThrowing(value = "execution(public int com.m.action_proxy.impl.CalImpl.*(..)))",throwing = "exception")
        public void afterThrowing(JoinPoint joinPoint,Exception exception){
            //获取方法名
            String name = joinPoint.getSignature().getName();
            System.out.println(name+"方法抛出异常:"+exception);
        }
    }
    
    

    方法注解:

    • @Before:表示切面方法执行的时机是业务方法执行之前。

    • @After:表示切面方法执行的时机是业务方法执行之后。

    • @AfterReturning:表示切面方法执行的时机是业务方法return之后。

    • @AfterThrowing:表示切面方法执行的时机是业务方法抛出异常之后。

    • execution(public int com.southwind.util.CalImpl.*(..)):表示切入点是com.southwind.util包下CalImpl类中的所有方法,即CalImpl所有方法在执行时会优先执行切面方法。






    备注:最近来手感,写了个类似Tomcat服务

    github地址:https://github.com/cnamep001/my_tomcat.git






  • 相关阅读:
    当今世界最为经典的十大算法投票进行时
    HDU_1203 I NEED A OFFER!
    POJ_2352 Stars(树状数组)
    HDU_1231 最大连续子序列
    POJ_3264 Balanced Lineup(线段树练手题)
    【转】休息几分种,学几个bash快捷键
    HDU_1013 Digital Roots
    HDU_1381 Crazy Search
    POJ_2528 Mayor's posters(线段树+离散化)
    zoj_1610 Count tht Color
  • 原文地址:https://www.cnblogs.com/k-class/p/13659493.html
Copyright © 2011-2022 走看看