当前位置: 移动技术网 > IT编程>开发语言>Java > spring源码AOP解析

spring源码AOP解析

2018年11月16日  | 移动技术网IT编程  | 我要评论

2018浙江卫视跨年演唱会,两小无猜糖衣恋,青蔷薇少女惨剧馆

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

静态代理:
|-- 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技术

|-- 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技术

|-- 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框架

|-- 定义注解类:
|-- @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

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网