• AOP学习


    Spring AOP 是基于jdk的动态代理和CGLIB代理实现的。广泛应用于处理一些具有横切性质的系统级服务,如日志、事务处理、缓存、性能统计、权限控制,异常处理等

    jdk动态代理:代理对象必须是某个接口的实现,它是通过运行期间创建接口的实现类来完成对目标对象的代理。

    CGLIB代理:它是在运行期间生成的代理对象是对目标对象扩展的子类。

    AOP在目标对象有接口时才有jdk动态代理实现,在没有接口时使用CGLIB代理实现。

    JDK动态代理实例:Subject 为接口,RealSubject 为实现类

    // 定义真实项目
    class RealSubject implements Subject {
        @Override
        public String say(String name, int age) {
            return name + "  " + age;
        }
    }
     
    class MyInvocationHandler implements InvocationHandler {
        private Object obj = null;
     
        public Object bind(Object obj) {
            this.obj = obj;
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
                    .getClass().getInterfaces(), this);
        }
     
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
           system.out.println("调用方法前执行操作…………");
            Object temp = method.invoke(this.obj, args);
           system.out.println("调用方法后执行操作");
            return temp;
        }
    }
     
    class hello {
        public static void main(String[] args) {
            MyInvocationHandler demo = new MyInvocationHandler();
            Subject sub = (Subject) demo.bind(new RealSubject());
            String info = sub.say("Rollen", 20);
            System.out.println(info);
        }
    }

    CGLIB代理举例:没有Subject 接口

    public class CGlibProxyFactory implements MethodInterceptor{
      private Object targetObject;
      
      public Object createProxyInstance(Object targetObject)
      { 
       this.targetObject=targetObject;
       Enhancer enhancer=new Enhancer();
       enhancer.setSuperclass(this.targetObject.getClass());//设置目标类的子类,该子类会覆盖所有父类中的非final方法
       enhancer.setCallback(this);//设置回调
      return  enhancer.create();
      }
    
     public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {
        RealSubject person=(RealSubject )this.targetObject;
        Object result=null;
        result = methodProxy.invoke(targetObject, args);
        return null;
     }
    }

    几个概念:

    连接点--joinpoint : 表示在哪干;

    切入点--pointcut:表示在哪干的集合;

    通知-- advice :表示干什么;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice)

    方面/切面 -- aspect : 表示在哪干和干什么的集合;

    引入 -- inter-type declaration :为已有类添加额外的字段和方法;

    目标对象 --Target object :表示对谁干;

    织入 -- weaving:是一个过程,表示将切面引入到目标对象,并创建AOP代理对象的过程。织入可以在编译期、类加载期、运行时。

    AOP实现方式:

    1、基于schema的AOP

    <aop:config> -------------------------------->AOP定义开始

             <aop:pointcut/> ----------------------->切入点定义

             <aop:advisor/> ----------------------->表示只有一个通知和一个切入点的切面,不推荐使用,因为有侵入性,必须实现通知API

             <aop:aspect> ------------------------>定义切面

                    <aop:pointcut/> ----------------->切入点定义

                    <aop:before/> ------------------->前置通知

                    <aop:after-returning/> ---------->后置返回通知

                    <aop:after-throwing/> ---------->后置异常通知

                    <aop:after/> ------------------->后置最终通知

                    <aop:around/> ------------------->环绕通知

                    <aop:declare-parents/> ---------->引入定义

             </aop:aspect>

    </aop:config>

    实例:

    1)定义目标接口

    package cn.javass.spring.chapter6.service;
    public interface IHelloWorldService {
        public void sayHello();
    }

    2)定义目标接口实现:

    package cn.javass.spring.chapter6.service.impl;
    import cn.javass.spring.chapter6.service.IHelloWorldService;
    public class HelloWorldService implements IHelloWorldService {
        @Override
        public void sayHello() {
            System.out.println("============Hello World!");
        }
    }

    3)定义切面支持类

    package cn.javass.spring.chapter6.aop;
        public class HelloWorldAspect {
            //前置通知
            public void beforeAdvice() {
                System.out.println("===========before advice");
        }
        //后置最终通知
        public void afterFinallyAdvice() {
            System.out.println("===========after finally advice");
        }
    }

    4)在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"
            xsi:schemaLocation="
               http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
        <bean id="helloWorldService" 
        class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/>
        
        <bean id="aspect" class="cn.javass.spring.chapter6.aop.HelloWorldAspect"/>
        <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* cn.javass..*.*(..))"/>
            <aop:aspect ref="aspect">
                <aop:before pointcut-ref="pointcut" method="beforeAdvice"/>
              <aop:after pointcut="execution(* cn.javass..*.*(..))" method="afterFinallyAdvice"/>
            </aop:aspect>
        </aop:config>
        
    </beans>

    2、基于注解@AspectJ的AOP

    Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:<aop:aspectj-autoproxy/>

    实例:

    1)2)同上

    3)定义切面支持类

    package cn.javass.spring.chapter6.aop;
    import org.aspectj.lang.annotation.Aspect;
    @Aspect
    public class HelloWorldAspect2 {   //定义切入点
        @Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", 
            argNames = "param")
        public void beforePointcut(String param) {}
    
        //定义通知
        @Before(value = "beforePointcut(param)", argNames = "param")
        public void beforeAdvice(String param) {
            System.out.println("===========before advice param:" + param);
        }
    }

    4)在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"
            xsi:schemaLocation="
               http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
          <aop:aspectj-autoproxy/>
        
          <bean id="helloWorldService" 
          class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/>
        
          <bean id="aspect" 
          class="cn.javass.spring.chapter6.aop.HelloWorldAspect2"/>
        
    
    </beans>
  • 相关阅读:
    Omi新成员omi-router正式发布
    Omi架构与React Fiber
    Omi框架Store体系的前世今生
    Omi v1.0震撼发布
    omi-cli新版发布-升级webpack2和支持sass生成组件局部CSS
    Omi应用md2site-0.5.0发布-支持动态markdown拉取解析
    Omi应用md2site发布-markdown转网站利器
    AlloyTouch之无限循环select插件
    Omi教程-插件体系
    AlloyTouch之select选择插件
  • 原文地址:https://www.cnblogs.com/mains/p/3392351.html
Copyright © 2020-2023  润新知