欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring源码AOP解析

程序员文章站 2022-05-18 22:52:40
1、代理技术(静态代理、JDK动态代理、CGLib代理) 静态代理: |-- Hello |-- void say(String name); |-- HelloImpl implements Hello { voiv say(String name){ sysout("Hello!"+name); ......

1、代理技术(静态代理、jdk动态代理、cglib代理)

spring源码AOP解析
静态代理:
|-- hello 
|-- void say(string name);
|-- helloimpl implements hello {
voiv say(string name){
    sysout("hello!"+name);
}
}
|-- helloproxy implents hello {
    hello hello; 
    helloproxy(){
        hello = new helloimpl();
    }
    voiv say(string name){
        before();
        sysout("hello!"+name);
        end();
    }
    void before(){
        sysout("before");
    }
    void after(){
        sysout("after");
    }
    
    main(string[] args){
        hello hello = new helloproxy();
        hello.say("jack");
    }
}
jdk动态代理:
|-- dynamicproxy implements invocationhandler {
    object target; 
    dynamicproxy (object target){
        this.target = target;
    }
    @override
    public object invoke(object proxy, method method, object[] args){
        before();
        object result = method.invoke(target, args);
        after();
        return result;
    }
    ...
    
    main(string[] args){
        // 尝试1
        hello hello = new helloimpl();
        dynamicproxy dynamicproxy = new dynamicproxy(hello);
        hello hello = (hello)proxy.newproxyinstance(hello.getclass().getclassloader(), hello.getclass.getinterfaces(), dynamicproxy);
        hello.say("jack");
        
        // 尝试2
        dynamicproxy dynamicproxy = new dynamicproxy(new helloimpl());
        hello hello = dynamicproxy.getproxy();
        hello.say("jack");
    }
    
    public <t> t getproxy(){
        return (t)proxy.newproxyinstance(
            target.getclass().getclassloader(), 
            target.getclass.getinterfaces(), 
            this
        );
    }
}

cglib动态代理:
|-- cglibproxy implements methodinterceptor {
    private static cglibproxy instance = new cglibproxy();
    
    private cglibproxy() {}
    
    public cglibproxy getinstance(){
        return instance;
    }

    public <t> t getproxy(class<t> cls){
        return (t) enhancer.create(cls, this);
    }
    public object inercept(object obj, method method, object[] args, methodproxy proxy){
        before();
        object result = proxy.invokesuper(obj, args);
        after();
        return result;
    }
    ...    
    
    main(string[] args){
        // 尝试1
        cglibproxy cglibproxy = new cglibproxy();
        hello helloproxy = cglibproxy.getproxy(helloimpl.class);
        helloproxy.say("jack");
        // 尝试2
        hello helloproxy =cglibproxy.getinstance().getproxy(helloimpl.class);
        helloproxy.say("jack");
    }
}
view code

2、aop技术

spring源码AOP解析
|-- interface greeting 
|-- void sayhello(string name);
|-- greetingimpl implements greeting
|-- sayhello(string name){
    before();
    sysout("hello!"+name);
    after();
}
|-- greetingproxy implements greeting
|-- greetingimpl greetingimpl;
|-- greetingproxy(greetingimpl greetingimpl) -> this.greetingimpl = greetingimpl;
|-- sayhello(string name){
    before();
    greetingimpl.sayhello();
    after();
}
|-- before() -> sysout("before");
|-- after() -> sysout("after");
|-- main(string[] args){
    greeting greetingproxy = new greetingproxy(new greetingimpl());
    greetingproxy.sayhello("jack");
}
|-- jdkdynamicproxy implements invocationhandler {
    object target; 
    jdkdynamicproxy (object target){
        this.target = target;
    }
    @override
    public object invoke(object proxy, method method, object[] args){
        before();
        object result = method.invoke(target, args);
        after();
        return result;
    }
    public <t> t getproxy(){
        return (t)proxy.newproxyinstance(
            target.getclass().getclassloader(), 
            target.getclass.getinterfaces(), 
            this
        );
    }
    private void before(){
        sysout("before");
    }
    private void after(){
        sysout("after");
    }
    
    main(string[] args){
        greeting greeting = new jdkdynamicproxy(new greetingimpl()).getproxy();
        greeting.sayhello("jack");
    }
}
|-- cglibproxy implements methodinterceptor{
    private static cglibproxy instance = new cglibproxy();
        
    private cglibproxy() {}
    
    public cglibproxy getinstance(){
        return instance;
    }

    public <t> t getproxy(class<t> cls){
        return (t) enhancer.create(cls, this);
    }
    public object inercept(object obj, method method, object[] args, methodproxy proxy){
        before();
        object result = proxy.invokesuper(obj, args);
        after();
        return result;
    }
    main(string[] args){
        greeting greeting = cglibproxy.getinstance().getproxy(greetingimpl.class);
        greeting.sayhello("jack");
    }
}
view code

3、spring aop技术

spring源码AOP解析
|-- greetingbeforeadvice implements methodbeforeadvice
    |-- before(method method, object[] args, object target) throws throwable -> sysout("before");
|-- afterreturningadvice 
    |-- afterreturning(object result, method method, object[] args, object target) throws throwable -> sysout("after");
|-- greetingbeforeandafteradvice implements methodbeforeadvice, afterreturningadvice
    |-- before(method method, object[] args, object target) throws throwable -> sysout("before");
    |-- afterreturning(object result, method method, object[] args, object target) throws throwable -> sysout("after");
|-- greetingaroundadvice implements methodinterceptor // 环绕增强(org.aopalliance.intercept.methodinterceptor,aop联盟)
    |-- object invoke(methodinvocation invocation){
        before();
        object result = invocation.proceed();
        after();
    }
    |-- before() -> sysout("before")
    |-- after() -> sysout("after")
|-- main (string[] args){
        proxyfactory proxyfactory = new proxyfactory(); // 创建代理工厂
        proxyfactory.settarget(new greetingimpl()); // 射入目标类对象
        // proxyfactory.addadvice(new greetingbeforeadvice()); // 添加前置增强
        // proxyfactory.addadvice(new afterreturningadvice()); // 添加后置增强
        // proxyfactory.addadvice(new greetingbeforeandafteradvice()); // 添加前后置增强
        proxyfactory.addadvice(new greetingaroundadvice()); // 添加环绕增强
        
        greeting greeting = (greeting)proxyfactory.getproxy(); // 从代理工厂获取代理对象
        greeting.sayhello("jack"); // 调用代理方法
    }
|-- 配置文件-spring.xml
    <!-- 扫描指定包(将带有@componet注解类自动定义为spring bean) -->
    <context:componet-scan base-package="aop.demo"/> 
    <!-- 配置一个代理 --> 
    <bean id="greetingproxy" class="org.springframework.aop.framework.proxyfactorybean">
        <property name="interfaces" value="aop.greeting"></property><!-- 需要代理的接口 -->
        <property name="target" value="greetingimpl"></property><!-- 接口实现类 -->
        <!-- <property name="target" value="greetingaroundadvice"></property> -->
        <property name="interceptornames">
            <list>
                <value>greetingaroundadvice</value>
            </list>
        </property>
    </bean>
    
    spring2.5+特性,@component
    @component
    public calss greetingimpl implements greeting {
        ...
    }
    --> 
    <bean id="xxx" class="xxx">
|-- 客户端调用
    |-- main(string[] args){
            applicationcontext context = new classpathxmlapplicationcontext("aop/demo/spring.xml");
            greeting greeting = (greeting)context.getbean("greetingproxy");
            greeting.sayhello("jack");
        }
|-- 抛出增强-throwsadvice
    |-- greetingthrowadvice implements throwsadvice {
            public void afterthrowing(method method, object[] args, object target, exception e){
                sysout("--------- throw exception ---------");
                sysout("target class: " + target.getclass().getname());
                sysout("method name: " + method.getname());
                sysout("exception message: " + e.getmessage());
                sysout("-----------------------------------");
            }
        }
|-- 引入增强
    |-- interface apology 
        |-- void saysorry(string name);
    |-- @component
        greetingintroadvice extends delegatingintroductioninterceptor implements apology {
            @override 
            public object invoke(methodinvocation invocation) throws throwable{
                return super.invoke(invocation);
            }
            
            @overrice
            public void saysorry(string name){
                sysout("sorry! + name);
            }
        }
    |-- 配置文件-spring.xml
        <!-- 扫描指定包(将带有@componet注解类自动定义为spring bean) -->
        <context:componet-scan base-package="aop.demo"/> 
        <!-- 配置一个代理 --> 
        <bean id="greetingproxy" class="org.springframework.aop.framework.proxyfactorybean">
            <property name="interfaces" value="aop.demo.apology"></property><!-- 需要动态实现的接口 -->
            <property name="target" value="greetingimpl"></property><!-- 目标类 -->
            <property name="interceptornames" value="greetingintroadvice"></property> <!-- 引入增强 -->
            <property name="proxytargetclass" value="true"/> <!-- 代理目标类(默认为false,代理接口)-->
        </bean>
    |-- 调用
        |-- main(string[] args){
            applicationcontext context = new classpathxmlapplicationcontext("aop/demo/spring.xml");
            geetingimpl greetingimpl = (geetingimpl)context.getbean("greetingproxy"); // 转型为目标类,而非它的接口
            greetingimpl.sayhello("jack");
            
            apology apology = (apology) greetingimpl; // 将目标类型强制向上转型为apology接口(这就是引入增强给我们带来的特性,也就是“接口动态实现”功能)
            apology.saysorry("jack");
        }
|-- aop 切面
    |-- @component
        public class greetingimpl implements greeting {
            @override
            public void sayhello(){
                sysout("hello!" + name);
            }
            
            public void goodmorning(string name){
                sysout("good morning!" + name);
            }
            public void goodnight(string name){
                sysout("good night!" + name);
            }
        }
    |-- 配置文件-spring.xml
        <!-- 扫描指定包(将带有@componet注解类自动定义为spring bean) -->
        <context:componet-scan base-package="aop.demo"/> 
        <!-- 配置一个切面 -->
        <bean id="greetingadvisor" class="org.springframework.aop.support.regexpmethodpointcutadvisor">
            <property name="advice" value="greetingaroundadvice"></property> <!-- 增强 -->
            <property name="pattern" value="aop.demo.greetingimpl.good.*"></property> <!-- 切点(正则表达式) -->
        </bean>
        
        <!-- 配置一个代理 --> 
        <bean id="greetingproxy" class="org.springframework.aop.framework.proxyfactorybean">
            <property name="target" value="greetingimpl"></property><!-- 目标类 -->
            <property name="interceptornames" value="greetingadvisor"></property><!-- 切面 -->
            <property name="proxytargetclass" value="true"/> <!-- 代理目标类(默认为false,代理接口)-->
        </bean>
|-- aop自动代理(每一个类都需要配置切面太麻烦,因此需要自动生成代理)
    |-- 配置文件-spring.xml
    <bean class="org.springframework.aop.framework.autoproxy.beannameautoproxycreator">
        <property name="target" value="*impl"></property><!-- 目标类 -->
        <property name="interceptornames" value="greetingaroundadvice"></property><!-- 增强 -->
        <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
    </bean>
    *impl -> 不清楚bean实现了多少接口,不能代理接口,只能代理类。
    |-- 匹配到目标类的指定方法
        |-- 配置文件-spring.xml
            <bean class="org.springframework.aop.framework.autoproxy.beannameautoproxycreator">
                <!-- <property name="target" value="*impl">--></property><!-- 目标类 -->
                <!-- <property name="interceptornames" value="greetingaroundadvice"></property>--><!-- 增强 -->
                <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
            </bean>
            --> 
            <bean id="greetingadvisor" class="org.springframework.aop.support.regexpmethodpointcutadvisor">
                <property name="advice" ref="greetingaroundadvice"></property> <!-- 增强 -->
                <property name="pattern" value="aop.demo.greetingimpl.good.*"></property> <!-- 切点(正则表达式) -->
            </bean>
            <bean class="org.springframework.aop.framework.autoproxy.defaultadvisorautoproxycreator">
                <property name="optimize" value="true"/> <!-- 是否对代理生成策略进行优化,默认是false -->
            </bean>

总结:
    cglib代理:创建代理速度慢,创建代理后运行速度快(系统初始化创建代理备用最佳)
    jdk动态代理:创建代理速度快,运行速度慢
    
|-- spring + aspectj(advisor)
|-- 普通demo
    |-- @aspect
        @component
        public class greetingaspect {
            @arount("execution(* aop.demo.greetingimpl.*(..))")
            public object around(proceedingjoinpoint pjp) throws throwable {
                before();
                object result = pjp.proceed();
                after();
                return result;
            }
            public void before(){
                sysout("before");
            }
            public void after(){
                sysout("after");
            }
        }
    |-- 配置文件-spring.xml
        <!-- 扫描指定包(将带有@componet注解类自动定义为spring bean) -->
        <context:componet-scan base-package="aop.demo"/> 
        <aop:aspect-autoproxy proxy-target-class="true" />    
|-- 基于注解
    |-- @target(elementtype.method)
        @retention(retentionpolicy.runtime)
        public @interface tag {
        }
    |-- @aspect
        @component
        public class greetingaspect {
            @arount("@annotation(aop.demo.tag)")
            public object around(proceedingjoinpoint pjp) throws throwable {
                ...
            }
            ...
        }
    |-- @component
        public class greetingimpl implements greeting {
            @tag
            @override 
            public void sayhello(string name){
                sysout("hello!" + name);
            }
            ...
        }
    |-- 实现引入增强
        |-- @aspect
            @component
            public class greetingaspect {
                
                @delareparents(value="aop.demo.greetingimpl",defaultimpl="apologyimpl.class")
                private apology apology;
            }
        |-- apologyimpl implements apology {
                
                @override
                public void saysorry(string name){
                    sysout("sorry!" + name);
                }
                main(string[] args){
                    applicationcontext context = new classpathxmlapplicationcontext("aop/demp/spring.xml");
                    greeting greeting = context.getbean("greetingimpl");
                    greeting.sayhello("jack");
                    apology apology = (apology) greeting;
                    apology.saysorry("jack");
                }
            }
        
|-- 基于配置
    |-- 配置文件-spring.xml
        <!-- 扫描指定包(将带有@componet注解类自动定义为spring bean) -->
        <context:componet-scan base-package="aop.demo"/>
        <beans ...>
            
            <bean id="greetingimpl" class="aop.demo.greetingimpl" />
            <bean id="greetingaspect" class="aop.demo.greetingaspect" />
            <aop:config>
                <aop:aspect ref="greetingaspect">
                    <aop:around method="around" pointcut="execution (* aop.demo.greetingimpl.*(..))"/>
                </aop:aspect>
            </aop:config>
        </beans>
view code

4、开发aop框架

spring源码AOP解析
|-- 定义注解类:
|-- @target(elementtype.type)
@retention(retentionpolicy.runtime)
public @interface aspect {
    class<? extends annotion> value();
}
|-- 搭建代理框架
|-- interface proxy { 代理接口
    // 执行链式代理:可将多个代理通过一条链子串起来,一个个地去执行,执行顺序取决于添加到链上的先后顺序
    object doproxy(proxychain proxychain) throws throwable;
}
|-- class proxychain // 代理链
|-- class<?> targetclass;
|-- object targetobject;
}-- method targetmethod;
|-- methodproxy methodproxy;
}-- object[] methodparams;
|-- list<proxy> proxylist = new arraylist<>();
|-- int proxyindex=0;
|-- proxchain(class<?> targetclass,object targetobject,method targetmethod,methodproxy methodproxy,object[] methodparams,list<proxy> proxylist){
        this.targetclass = targetclass;
        ...
    }
|-- getmethodparams() -> return methodparams;
|-- gettargetclass() -> return targetclass;
|-- gettargetmethod() -> return targetmethod;
|-- object doproxychain() throws throwable{
        object methodresult;
        if (proxyindex < proxylist.size()){
            methodresult = proxylist.get(proxyindex++).doproxy();
        } else {
            methodresult = methodproxy.invokesuper(targetobject, methodparams);
        }
        return methodresult;
    }
|-- 添加pom.xml依赖
<!-- cglib 依赖-->
<grouid>cglib<groupid>...
|-- class proxymanger // 代理管理类
|-- <t> t createproxy(final class<?> targetclass, final list<proxy> proxylist){
        return (t) enhancer.create(targetclass, new methodinterceptor(){
            @overrice
            public object intercept(object targetobject, method targetmethod, 
                object[] methodparams, methodproxy methodproxy){
                return new proxychain(targetclass, targetobject, targetmethod, methodproxy, methodparams, proxylist);
            }
        });
    }
|-- public abstract calss aspectproxy implements proxy { // 切面代理
    @override
    public final object doproxy(proxychain proxychain) throws throwable {
        object result = null;
        class<?> cls = proxychain.gettargetclass();
        method method = proxychain.gettargetmethod();
        object[] params = proxychain.getmethodparams();
        begin();
        try {
            if (intercept(cls, method, params)){
                before(cls, method, params);
                result = proxychain.doproxychain();
                after(cls, method, params);
            } else {
                return proxychain.doproxychain();
            }
        } catch(exception e){
            logger.error("proxy failure", e);
            error(cls, method, params, e);
            throw e;
        } finally {
            end();
        }
    }
    public void begin(){
    }
    public void end(){
    }
    public boolean intercept(class<?> cls, method method, object[] params) throws throwable {
        return true;
    }
    public void before(class<?> cls, method method, object[] params) throws throwable {
    }
    public void after(class<?> cls, method method, object[] params) throws throwable {
    }
    public void error(class<?> cls, method method, object[] params, throwable e){
    }
}
|-- @aspect(controller.class)
controlleraspect extends aspectproxy{ // 拦截controller    所有方法
    private long begin;
    @override
    public void before(class<?> cls, method method, object[] params) throws throwable {
        begin = system.currenttimemillis();
    }
    @override
    public void after(class<?> cls, method method, object[] params) throws throwable {
        sysout(system.currenttimemillis()-begin);
    }
}
|-- beanhelper {
    ...
    // 设置bean实例 
    public static void setbean(class<?> cls, object obj){
        bean_map.put(cls, obj);
    }
}    
|-- classhelper {
    ...
    // 获取某父类(或接口)的所有子类(或实现类)
    public static set<class<?>> getclasssetbysuper(class<?> superclass){
        set<class<?>> classset = new hashset<classs<?>();
        for(class<?> cls : class_set){
            if (superclass.isassignablefrom(cls) && !superclass.equals(cls)){
                classset.add(cls);
            }
        }
    } 
    // 获取应用包名下带有注解的所有类
    public static set<class<?>> getclasssetbyannotation(class<? extends annotation> annotionclass){
        set<class<?>> classset = new hashset<classs<?>();
        for(class<?> cls : class_set){
            if (superclass.isannotationpresent(annotionclass)){
                classset.add(cls);
            }
        }
    }
    ...
}
|-- aophelper {
    ...
    private static set<class<?>> createtargetclassset(aspect aspect) throws exception {
        set<class<?>> targetclassset = new hashset<class<?>>();
        class<? extends annotation> annotation = aspect.value();
        if (annotation != null && !annotation.equals(aspect.class)){
            targetclassset.addall(classhelper.getclasssetbyannotation(annotation));
        }
        return targetclassset;
    }
    private static map<class<?>>,set<class<?>>> createproxymap() throws exception {
        map<class<?>>,set<class<?>>> proxymap = new hashmap<class<?>>,set<class<?>>>();
        set<class<?>> proxyclassset = classhelper.getclasssetbyannotation(aspectproxy.class);
        for(class<?> proxyclass : proxyclassset){
            if (proxyclass.isannotationpresent(aspect.class)){
                aspect aspect = proxyclass.getannotation(aspect.class);
                set<class<?>> targetclassset = createtargetclassset(aspect);
                proxymap.put(proxyclass, targetclassset);
            }
        }
        return proxymap;
    }    
    private static map<class<?>,list<proxy>> createtargetmap(map<class<?>>,set<class<?>>> proxymap) throws exception {
        map<class<?>,list<proxy>> targetmap = new hashmap<class<?>,list<proxy>>();
        for(map.entry<class<?>>,set<class<?>>> proxyentry : proxymap.entryset()){
            class<?> proxyclass = proxyentry.getkey();
            set<class<?> targetclassset = proxyentry.getvalue();
            for(class<?> targetclass : targetclassset){
                proxy proxy = (proxy) targetclass.newinstance();
                if (targetmap.contains(targetclass)){
                    targetmap.get(targetclass).add(proxy);
                } else {
                    list<proxy> proxylist = new arraylist<proxy>();
                    proxylist.add(proxy);
                    targetmap.put(targetclass, proxylist);
                }
            }
        }
    }
    
    static {
        try {
            map<class<?>>,set<class<?>>> proxymap = createproxymap();
            map<class<?>,list<proxy>> targetmap = createtargetmap(proxymap);
            for(map.entry<class<?>,list<proxy>> targetentry : targetmap.etryset()){
                class<?> targetclass =targetentry.getkey();
                list<proxy> proxylist = targetentry.getvalue();
                object proxy = proxymanager.createproxy(targetclass, proxylist);
                beanhelper.setbean(targetclass, proxy);
            }
        } catch(exception e){
            logger.error("aop failure", e);
        }
    }
}
|-- helperloader {
    public static void init(){
    
        class<?>[] classlist = {
            classhelper.class, 
            beanhelper.class,
            aophelper.class,
            iochelper.class,
            controllerhelper.class
        };
        for(class<?> cls : classlist){
            classutil.loadclass(cls.getname(), true);
        }
    }
}
view code

 

上一篇: 1

下一篇: springboot集合jpa使用