曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享
曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解
曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下
曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?
曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean
曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的
曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)
曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)
曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)
曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)
曹工说Spring Boot源码(11)-- context:component-scan,你真的会用吗(这次来说说它的奇技淫巧)
曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)
曹工说Spring Boot源码(13)-- AspectJ的运行时织入(Load-Time-Weaving),基本内容是讲清楚了(附源码)
曹工说Spring Boot源码(14)-- AspectJ的Load-Time-Weaving的两种实现方式细细讲解,以及怎么和Spring Instrumentation集成
曹工说Spring Boot源码(15)-- Spring从xml文件里到底得到了什么(context:load-time-weaver 完整解析)
曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)
曹工说Spring Boot源码(17)-- Spring从xml文件里到底得到了什么(aop:config完整解析【中】)
曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】)
工程代码地址 思维导图地址
工程结构图:
概要本篇是接着前三篇讲的,但是本篇相对独立,即使不使用spring aop 和spring ioc,我们也可以利用今天要讲的ProxyFactory为我们所用。
曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)
曹工说Spring Boot源码(17)-- Spring从xml文件里到底得到了什么(aop:config完整解析【中】)
曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】)
前面几篇说到,spring如何实现aop,即将匹配切点的bean,生成动态代理,并将生成的动态代理放到ioc容器,来替换原先的bean,一系列骚操作,完成"代理换真身"的操作。
jdk动态代理比较老套的话题,但是,我问大家几个问题,看看大家是否真的足够了解他呢?
在代理对象上,调用不在接口中的方法 package foo; public class Performer implements Perform { @Override public void sing() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("男孩在唱歌"); } public void eat() { System.out.println("男孩在吃饭"); } }可以看到,我们sing是实现了接口中的方法,而eat不在接口中定义。
那么,如下代码,结果会是啥:
@Test public void createJdkDynamicProxyManual() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Object generatedProxy = Proxy.newProxyInstance(loader, new Class[]{Perform.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("proxy:" + proxy.getClass()); return "hahh"; } }); Method eat = Perform.class.getMethod("eat"); eat.setAccessible(true); eat.invoke(generatedProxy,null); }代码中,我们创建了一个代理对象:generatedProxy;然后,调用了其eat方法,结果会是啥呢?
java.lang.NoSuchMethodException: foo.Perform.eat() at java.lang.Class.getMethod(Class.java:1665) at java.lang.Class.getMethod(Class.java:1665)为啥会这样呢?因为我们创建代理对象时,是在Perform.class这个接口上创建的。大家可以再仔细看看。
jdk 动态代理(Proxy.newProxyInstance)有哪几个步骤这个问题,有人思考过吗?简单来说,其实有3个步骤。
生成动态代理类的class,虽然不像其他class文件那样,是编译了就有的,这里,是动态生成的;
加载第一步拿到的字节流,丢给jvm加载该class,拿到Class对象
根据第二步的Class对象,反射生成动态代理对象。