模仿 Spring 實(shí)現(xiàn)一個(gè)類管理容器
概述
項(xiàng)目的初衷是獨(dú)立作出一個(gè)成熟的有特色的IOC容器,但由于過(guò)程參考Spring太多,而且也無(wú)法作出太多改進(jìn),于是目的變?yōu)橐源隧?xiàng)目作為理解Spring的一個(gè)跳板,與網(wǎng)上的一些模仿Spring的框架不同,本項(xiàng)目主要是針對(duì)注解形式
地址是Thales
流程
在Spring中,一個(gè)bean的形成分三個(gè)大的階段,
bean的定義階段(包含BeanDefinition的加載,解析,與注冊(cè))
bean的實(shí)例化階段(包含對(duì)象的創(chuàng)建,屬性的注入)
bean的初始化階段(包含一些資源的初始化,譬如打開(kāi)文件建立連接等等)
這只是大概的劃分,關(guān)于BeanPostProcessor等后置處理并沒(méi)有顯式的提及.
類的設(shè)計(jì)
如果只想了解一個(gè)bean是怎么從生到死的,只需要一步步debug就好了,如果看不懂,就多debug幾遍.可是如果想實(shí)現(xiàn)一個(gè)類似的容器,類的設(shè)計(jì),職責(zé)的分配,接口的實(shí)現(xiàn)繼承必然是要了解的(除非你想幾個(gè)類做完所有的事)
以下是DefaultListableBeanFactory的類圖
是不是頂不住
我們?cè)賮?lái)看一張圖
第一張是Spring5.0的,第二張圖是Spring0.9的,所以并沒(méi)有必要在一開(kāi)始就引入過(guò)多的設(shè)計(jì)復(fù)雜度
我們?cè)賮?lái)看一套對(duì)比圖
哪一個(gè)是0.9的,哪一個(gè)是5.0的一目了然.
說(shuō)這么多的目的,是說(shuō)明我們沒(méi)必要一開(kāi)始就奔著最完善的目標(biāo)去寫(xiě),可以一步步來(lái),一步步加入功能
實(shí)現(xiàn)簡(jiǎn)易IOC
眾所周知,SpringIoC中最基本的就是BeanFactory
我們先定義一個(gè)BeanFactory接口
- //暫時(shí)就給這一個(gè)方法public interface BeanFactory { /** * 根據(jù)名字獲取Bean實(shí)例 * @param name * @return */ Object getBean(String name);}
beanDefinition
由于是注解形式,我們不能再像xml那樣給定一個(gè)資源文件再去解析了,而應(yīng)該去掃描classPath下所有帶有@Component的類,
這時(shí)候我們需要給定的參數(shù)就從文件路徑變成了包路徑,我們只需要掃描這個(gè)包及其子包內(nèi)符合條件的類,并且將其轉(zhuǎn)化為BeanDefinition再注冊(cè)就好.執(zhí)行這個(gè)功能的是ClassPathBeanDefinitionScanner這個(gè)類.在這一步,就已經(jīng)和傳統(tǒng)的流程有所區(qū)別了,我們會(huì)傳入一個(gè)ResourceLoader去實(shí)現(xiàn)具體的掃描功能(即定位),但不會(huì)再有專門的類去處理解析這一步
- public interface Resource { File getFile(); String getFilename(); String getFilePath();}//在最初設(shè)計(jì)的時(shí)候這個(gè)抽象類似乎沒(méi)有用,但考慮到以后的擴(kuò)展,還是先放在這public abstract class AbstractResource implements Resource { @Override public String getFilename() { return getFile().getName(); } @Override public String getFilePath() { return getFile().getPath(); }}//這就是最終我們實(shí)例化bean時(shí)用到的Resource類,在Spring中并沒(méi)有直接用,而是通過(guò)外觀模式集成了一下成為RootBeanDefinitionpublic class ClassPathResource extends AbstractResource { private final String path; private ClassLoader classLoader; private Class<?> clazz; public ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) { this.path = path; this.classLoader = classLoader; this.clazz = clazz; }}
- public interface ResourceLoader { Resource getResource(String location);}//此類能夠?qū)崿F(xiàn)加載多個(gè)資源public interface ResourcePatternResolver extends ResourceLoader { String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; List<? extends Resource> getResources(String location);}//這個(gè)類就是正式用于掃描的類了public class PathMatchingResourcePatternResolver implements ResourcePatternResolver { private final ResourceLoader resourceLoader; public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader){ this.resourceLoader = resourceLoader; } @Override public Resource getResource(String location) { return resourceLoader.getResource(location); }//在Spring中,是通過(guò)一層層方法的包裝完成包名到路徑的轉(zhuǎn)換再到每個(gè)文件的掃描再轉(zhuǎn)換為Resource,這里暫時(shí)就先一步到位,把具體實(shí)現(xiàn)放在工具類里 @Override public List<? extends Resource> getResources(String location) { Set<Class<?>> classes = ClassUtils.getClasses(location); List<ClassPathResource> classPathResources = new ArrayList<>(); for (Class<?> clazz:classes) { classPathResources.add(new ClassPathResource("",clazz.getClassLoader(),clazz)); } return classPathResources; }}
但最后直接使用的并不是PathMatchingResourcePatternResolver
而是把他作為ClassPathBeanDefinitionScanner的一個(gè)屬性,在這個(gè)類里調(diào)用.
我們得到了Resource,如何獲得對(duì)應(yīng)的BeanDefinition?
先考慮這樣一個(gè)問(wèn)題,什么樣的類可以被注冊(cè)BeanDefinition?
添加了@Component注解或者滿足其他注冊(cè)的條件
不是接口或者抽象類
所以我們可以單獨(dú)抽象出一個(gè)方法 boolean isCandidateComponent(Class<?> clazz)來(lái)判斷是否被注冊(cè)
現(xiàn)在到了注冊(cè)階段,依舊秉持面向接口編程的理念,同時(shí)考慮到單一職責(zé),我們把注冊(cè)Bean定義單獨(dú)抽象出來(lái)
- public interface BeanDefinitionRegistry { void registerBeanDefinition(BeanDefinition beanDefinition);}
上文說(shuō)到Bean定義的定位,解析,注冊(cè)都是在ClassPathBeanDefinitionScanner里完成的,于是BeanDefinitionRegistry自然也成為了ClassPathBeanDefinitionScanner的屬性之一
于是ClassPathBeanDefinitionScanner構(gòu)建完成了
- public class ClassPathBeanDefinitionScanner { //負(fù)責(zé)具體的Resource定位 private ResourcePatternResolver resourcePatternResolver; //負(fù)責(zé)BeanDefinition解析 private BeanDefinitionRegistry registry; public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry,String...basePackage) { this.registry = registry; this.resourcePatternResolver = new PathMatchingResourcePatternResolver((ResourceLoader) registry); this.scan(basePackage); } public void scan(String...basePackages){ doScan(basePackages); } void doScan(String[] basePackages){ Set<BeanDefinition> beanDefinitions = new LinkedHashSet<>(); for (String basePackage:basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for(BeanDefinition candidate:candidates){ beanDefinitions.add(candidate); registry.registerBeanDefinition(candidate); } } } //獲取被注冊(cè)的bean的集合 private Set<BeanDefinition> findCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); List<? extends Resource> resources = getResourcePatternResolver().getResources(basePackage); for(Resource resource:resources){ if(resource instanceof ClassPathResource){ ClassPathResource classPathResource = (ClassPathResource)resource; if(isCandidateComponent(classPathResource.getClazz())){ AnnotationBeanDefinition beanDefinition = new AnnotationBeanDefinition(); beanDefinition.setClazz(classPathResource.getClazz()); beanDefinition.setBeanName(BeanUtils.generateBeanName(classPathResource.getClazz().getName())); candidates.add(beanDefinition); } } } return candidates; } private ResourcePatternResolver getResourcePatternResolver() { return this.resourcePatternResolver; } //判斷是否被注冊(cè) boolean isCandidateComponent(Class<?> clazz){ Component declaredAnnotation = clazz.getDeclaredAnnotation(Component.class); return declaredAnnotation!=null&&!clazz.isInterface(); } ;}
實(shí)例化
在什么時(shí)候?qū)嵗?我們說(shuō),在調(diào)用getBean()而又沒(méi)有現(xiàn)成的bean時(shí)進(jìn)行實(shí)例化
- public abstract class AbstractBeanFactory implements BeanFactory{ @Override public Object getBean(String beanName) }
對(duì)象創(chuàng)建
有兩種方式,通過(guò)Jdk默認(rèn)的反射實(shí)現(xiàn),或者用cglib代理實(shí)現(xiàn).
默認(rèn)自然是無(wú)參構(gòu)造,但是如果傳入了參數(shù),則需要根據(jù)參數(shù)的類型和數(shù)量去匹配對(duì)應(yīng)的構(gòu)造函數(shù),用其去實(shí)例化
于是我們抽象出InstantiationStrategy作為實(shí)例化接口,兩種實(shí)例化方法都需要實(shí)現(xiàn)這個(gè)接口,我們真正去用的時(shí)候只需要去調(diào)該接口的方法就好
- public interface InstantiationStrategy { Object instantiate(BeanDefinition beanDefinition, String beanName, BeanFactory owner);}public class SimpleInstantiationStrategy implements InstantiationStrategy {}
屬性注入
字段值獲取
有兩種方式可以實(shí)現(xiàn)字段值獲取
直接注解Autowired或者Value
Value里面填的不是值而是占位符,那么就需要解析占位符去獲取
我們通過(guò)Class對(duì)象獲取所有字段,再通過(guò)遍歷所有字段查找加在字段上的注解來(lái)獲取(這僅僅只是Spring的一種注入方式)
- //處理@Autowired注解 for(Field field:declaredFields){ Autowired autowired = field.getDeclaredAnnotation(Autowired.class); if(autowired != null){ pvs.add(new PropertyValue(field.getName(),new BeanReference(BeanUtils.generateBeanName(field.getType().getName()),field.getType()))); } } //處理@Value注解 for(Field field:declaredFields){ Value value = field.getDeclaredAnnotation(Value.class); if(value != null){ String value1 = value.value(); pvs.add(new PropertyValue(field.getName(),value1)); } }
字段值填充
獲取字段值后通過(guò)反射填入相應(yīng)的字段中
- for(Field field:mbd.getBeanClass().getDeclaredFields()){ field.setAccessible(true); if (field.getName().equals(propertiesValue.getName())&&field.getType().isAssignableFrom(newValue.getClass())) { field.set(bean,newValue); } }
初始化
調(diào)用指定的初始化方法,進(jìn)行資源的初始化.,如何獲取初始化方法?在xml模式中,只要加個(gè)標(biāo)簽即可,如果是注解模式,加個(gè)注解標(biāo)識(shí)一下或者在某個(gè)注解上加個(gè)參數(shù),代表初始化方法,這個(gè)還沒(méi)有實(shí)現(xiàn)
功能填充
后置處理器添加
上面我們已經(jīng)實(shí)現(xiàn)了一個(gè)可以進(jìn)行依賴查找,依賴注入的Bean容器,讓我們?cè)倩仡櫼幌耂pring的流程,我們少了些什么,最容易想到的應(yīng)該就是后置處理器了,包括BeanFactoryPostProcessor和BeanPostProcessor兩種,前者對(duì)于beanFactory進(jìn)行修改操作,后者對(duì)于bean進(jìn)行修改操作,同樣是面向接口編程
首先建立BeanPostProcessor
- public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName); Object postProcessAfterInitialization(Object bean, String beanName) ;}
就目前來(lái)看,有什么是需要BeanPostProcessor來(lái)做的呢?我們可以把之前對(duì)注解進(jìn)行處理,獲取注入屬性的代碼分離出來(lái),專門用一個(gè)BeanPostProcessor去處理
所有自定義實(shí)現(xiàn)的BeanPostProcessor都需要繼承這個(gè)接口,由于BeanPostProcessor的作用是處理其他的Bean,所以必須要在其他被處理的Bean實(shí)例化之前被創(chuàng)建出來(lái).于是我們?cè)趂inishBeanFactoryInitialization(beanFactory);之前添加registerBeanPostProcessors(beanFactory);用于實(shí)例化所有的BeanPostProcessor
而這些beanPostProcessor的重要程度是不同的,例如處理注解注入的BeanPostProcessor優(yōu)先級(jí)就要比一般的BeanPostProcessor優(yōu)先級(jí)要高,所以需要先實(shí)例化
Aware接口添加
其實(shí)現(xiàn)在我們已經(jīng)可以完全的把一個(gè)對(duì)象交由IOC容器了,但此時(shí)這個(gè)對(duì)象與容器之間的關(guān)系是單向的,容器能夠操作bean,但bean不能借助容器,為了解決此類問(wèn)題,我們添加一個(gè)Aware接口作為標(biāo)志接口,由各個(gè)更具體的Aware去繼承他,并在實(shí)例化屬性之后,初始化方法執(zhí)行之完成相關(guān)容器屬性的注入
事件監(jiān)聽(tīng)器添加
監(jiān)聽(tīng)器是觀察者模式的一種實(shí)現(xiàn)
我們先定義以下幾個(gè)基本接口
- public interface ApplicationEventPublisher { /** * 發(fā)布事件 * @param event */ void publishEvent(ApplicationEvent event);}public interface ApplicationEventMulticaster { /** * 添加廣播事件 * @param event */ void multicastEvent(ApplicationEvent event); /** * 添加對(duì)于某個(gè)事件的監(jiān)聽(tīng)器 * @param listener */ void addApplicationListener(ApplicationListener listener); /** * 移除指定監(jiān)聽(tīng)器 * @param listener */ void removeApplicationListener(ApplicationListener listener);}public interface ApplicationListener <E extends ApplicationEvent> extends EventListener { /** * 監(jiān)聽(tīng)特定事件 * @param event */ void onApplicationEvent(E event);}
具體調(diào)用流程為具體的listener被添加到廣播器中,事件通過(guò)publisher統(tǒng)一發(fā)布,而publishEvent最后會(huì)調(diào)用 multicastEvent(ApplicationEvent event)方法,經(jīng)過(guò)相應(yīng)判斷后由對(duì)應(yīng)監(jiān)聽(tīng)器做出相應(yīng)操作.
如何判斷這個(gè)監(jiān)聽(tīng)器是否對(duì)該事件感興趣?
我們事先實(shí)現(xiàn)的listener是有泛型的,我們可以通過(guò)這個(gè)泛型與傳入的事件類型的關(guān)系來(lái)判斷
- public boolean supportEvent(ApplicationListener<ApplicationEvent> listener,ApplicationEvent event){ //先獲取Class對(duì)象 Class<? extends ApplicationListener> listenerClass = listener.getClass(); //獲取其實(shí)現(xiàn)的所有接口(包括泛型信息) Type[] genericInterfaces = listenerClass.getGenericInterfaces(); for (Type genericInterface:genericInterfaces){ //判斷是否為泛型接口 if(genericInterface instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) genericInterface; //得到所有泛型參數(shù) Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type actualTypeArgument:actualTypeArguments){ try { Class<?> aClass = Class.forName(actualTypeArgument.getTypeName()); //判斷感興趣的事件類型是否與傳入事件相同,或者是其父類 if(aClass.isAssignableFrom(event.getClass())){ return true; } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } return false; }
FactoryBean添加
目前的Bean都是由BeanFactory來(lái)產(chǎn)生的,
我們用FactoryBean接口來(lái)標(biāo)識(shí)這個(gè)產(chǎn)生Bean的特殊的Bean
循環(huán)依賴的解決
循環(huán)依賴是指A依賴于B的同時(shí)B依賴于A,解決方法為實(shí)例化與初始化分離,如果只考慮一般情況的話用兩級(jí)緩存實(shí)際上就夠了,
代碼優(yōu)化
實(shí)現(xiàn)簡(jiǎn)易AOP
如果從正統(tǒng)的AOP開(kāi)始的話,隨之而來(lái)的就是一堆概念,包括切點(diǎn),通知一類
我們先看AOP要做什么
所以說(shuō)AOP的核心就是動(dòng)態(tài)代理,我們以Cglib為例來(lái)看看動(dòng)態(tài)代理要怎么用
- Enhancer enhancer = new Enhancer();//1. 為哪個(gè)類進(jìn)行代理 enhancer.setSuperclass(Buy.class); enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> { //2. 為該類的哪個(gè)方法進(jìn)行代理 if(method.getName().equals("buyOne")){ //3. 代理究竟要做什么 System.out.println("hello"); } //4. 調(diào)用原有的對(duì)象 methodProxy.invokeSuper(o,objects); return o; });//5. 產(chǎn)生代理后的對(duì)象 Buy o = (Buy)enhancer.create();
這就是動(dòng)態(tài)代理最核心的功能,也是AOP的核心功能,AOP的最終目的是代碼5,即產(chǎn)生一個(gè)代理對(duì)象,把這個(gè)代理對(duì)象交給IOC去管理
而為了達(dá)成這個(gè)目的,AOP框架需要做好代碼1-4所需要做的事,一和二組合起來(lái),成了JoinPoint,3叫做Advice,這兩個(gè)組合起來(lái)就叫做Advisor,可不可以不分這些種類,就全寫(xiě)在一個(gè)或幾個(gè)類里,當(dāng)然可以,Spring0.9就是這么做的,但發(fā)展到如今,早已采用了這種劃分方式.本項(xiàng)目也采用這種分類.
先從連接點(diǎn)說(shuō)起,如何確定到底在哪里實(shí)現(xiàn)功能增強(qiáng),無(wú)非是類與方法兩個(gè)層次;
我們先定義ClassFilter與MethodMacther兩個(gè)接口
- public interface ClassFilter { /** * 給定類型是否匹配 * @param clazz * @return */ boolean matches(Class< ? > clazz);}public interface MethodMatcher { /** * 對(duì)應(yīng)類的對(duì)應(yīng)方法是否匹配 * @param method * @param targetClass * @return */ boolean matches(Method method,Class< ? > targetClass);}
這兩個(gè)接口必然是組合起來(lái)使用的,于是我們用PointCut將其組合起來(lái)
- public interface Pointcut { /** * 獲取ClassFilter * @return */ ClassFilter getClassFilter(); /** * 獲取MethodMatcher * @return */ MethodMatcher getMethodMatcher();}
接口只是定義了抽象功能,這些功能還要有具體的實(shí)現(xiàn)
我們默認(rèn)用Java的正則去匹配方法名,以此構(gòu)建出JdkRegexMethodMatcher
- public class JdkRegexMethodPointcut implements MethodMatcher, Pointcut{ private Pattern[] compiledPatterns = new Pattern[0]; @Override public ClassFilter getClassFilter() { return null; } @Override public MethodMatcher getMethodMatcher() { return this; } @Override public boolean matches(Method method, Class<?> targetClass) { String name = method.getName(); for (Pattern pattern :compiledPatterns) { Matcher matcher = pattern.matcher(name); if(matcher.matches()){ return true; } } return false; } //預(yù)編譯 private Pattern[] compilePatterns(String[] source) throws PatternSyntaxException { Pattern[] destination = new Pattern[source.length]; for (int i = 0; i < source.length; i++) { destination[i] = Pattern.compile(source[i]); } return destination; } public void initPatternRepresentation(String[] patterns) throws PatternSyntaxException { this.compiledPatterns = compilePatterns(patterns); }}
在Spring中,并不是直接繼承的MethodMatcher,考慮到正則的語(yǔ)法不同,額外做了一層抽象,但在此處省略掉了
而JdkRegexMethodMatcher同時(shí)也實(shí)現(xiàn)了PointCut類,也就是說(shuō),現(xiàn)在切點(diǎn)已經(jīng)準(zhǔn)備好了
再來(lái)看Advice
由于考慮的可擴(kuò)展點(diǎn)比較多,于是繼承的層次也變的多了
- public interface Advice {}public interface BeforeAdvice extends Advice{}public interface MethodBeforeAdvice extends BeforeAdvice{ void before(Method method, Object[] args, Object target) throws Throwable;}
現(xiàn)在Advice也定義完了,具體的實(shí)現(xiàn)我們交由用戶去做
接下來(lái)就是整合成Advisor了
- public interface Advisor { Advice getAdvice();}public interface PointcutAdvisor extends Advisor{ Pointcut getPointcut();}public abstract class AbstractPointcutAdvisor implements PointcutAdvisor{ private Advice advice; @Override public Advice getAdvice() { return advice; } public void setAdvice(Advice advice) { this.advice = advice; }}
目前已經(jīng)定義好了Advisor的功能
我們?cè)賹?shí)現(xiàn)這個(gè)接口
- public class RegexMethodPointcutAdvisor extends AbstractPointcutAdvisor { JdkRegexMethodPointcut pointcut = new JdkRegexMethodPointcut(); private String[] patterns; public RegexMethodPointcutAdvisor() { } public RegexMethodPointcutAdvisor(Advice advice) { setAdvice(advice); } public void setPattern(String pattern) { setPatterns(pattern); } public void setPatterns(String... patterns) { this.patterns = patterns; pointcut.initPatternRepresentation(patterns); } @Override public Pointcut getPointcut() { return pointcut; }}
RegexMethodPointcutAdvisor就整合了PointCut以及Advice,通過(guò)他,我們就可以確定在何處做何種增強(qiáng).
現(xiàn)在的advisor可以完成檢驗(yàn)一個(gè)類是否要被代理的功能,但是如果這個(gè)類需要被代理,advisor卻無(wú)法保存這個(gè)類的對(duì)應(yīng)信息
于是我們需要一個(gè)類將advisor與對(duì)應(yīng)的代理類結(jié)合起來(lái),這就是AdvisedSupport
- public class AdvisedSupport { private TargetSource targetSource; private List<MethodInterceptor> methodInterceptors = new ArrayList<>(); private List<PointcutAdvisor> advisors = new ArrayList<>(); public TargetSource getTargetSource() { return targetSource; } public void setTargetSource(TargetSource targetSource) { this.targetSource = targetSource; } public List<MethodInterceptor> getMethodInterceptor() { return methodInterceptors; } public void addMethodInterceptor(MethodInterceptor methodInterceptor) { this.methodInterceptors.add(methodInterceptor); } public List<PointcutAdvisor> getAdvisor() { return advisors; } public void addAdvisor(PointcutAdvisor advisor) { MethodBeforeAdviceInterceptor methodBeforeAdviceInterceptor = new MethodBeforeAdviceInterceptor(); methodBeforeAdviceInterceptor.setAdvice((MethodBeforeAdvice) advisor.getAdvice()); addMethodInterceptor(methodBeforeAdviceInterceptor); this.advisors.add(advisor); }}
上類屬性中的TargetSource便是真正持有代理對(duì)象信息的類
現(xiàn)在萬(wàn)事具備,只需要用Cglib去使用我們已經(jīng)持有的信息就可以創(chuàng)建出新的類了
- public class CglibAopProxy implements AopProxy{ private final AdvisedSupport advised; public CglibAopProxy(AdvisedSupport advised) { this.advised = advised; } @Override public Object getProxy() { Enhancer enhancer = new Enhancer(); //1. 為哪個(gè)類進(jìn)行代理 enhancer.setSuperclass(advised.getTargetSource().getTargetClass()); enhancer.setCallback(new DynamicAdvisedInterceptor(advised)); //5. 產(chǎn)生代理后的對(duì)象 return enhancer.create(); } private static class DynamicAdvisedInterceptor implements MethodInterceptor { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { CglibInvocation cglibInvocation = new CglibInvocation(method,objects,o,methodProxy); //2. 為該類的哪個(gè)方法進(jìn)行代理 for(PointcutAdvisor advisor: advised.getAdvisor()){ if(advisor.getPointcut().getMethodMatcher().matches(method,advised.getTargetSource().getTargetClass())){ //3. 代理究竟要做什么 return advised.getMethodInterceptor().get(0).invoke(cglibInvocation); } } //4. 調(diào)用源方法 return cglibInvocation.proceed(); } }}
將這份代碼與最初使用cglib的代碼比較,會(huì)發(fā)現(xiàn)過(guò)程幾乎是一模一樣.但是作為一個(gè)框架,應(yīng)該盡可能的給用戶以方便
于是我們需要一個(gè)Creator去把這一切都做好,他需要負(fù)責(zé)將Advice和PointCut組合成Advisor,再將Advisor與TargetSource組裝成AdvisedSupport,再將AdvisedSupport交給Cglib動(dòng)態(tài)代理,產(chǎn)生代理對(duì)象,而用戶只需要編寫(xiě)Advice以及切入點(diǎn)表達(dá)式即可
功能演示
屬性注入基本類型引用類型循環(huán)依賴
容器感知
FactoryBean生成對(duì)象
AOP切面增強(qiáng)
自定義BeanPostProcessor
困難及解決
首先是設(shè)計(jì)上的問(wèn)題
FactoryBean的實(shí)現(xiàn)
AOP與IOC的結(jié)合
字段的注入