javascript
模仿Spring实现一个类管理容器
簡(jiǎn)介:?項(xiàng)目的初衷是獨(dú)立作出一個(gè)成熟的有特色的IOC容器,但由于過(guò)程參考Spring太多,而且也無(wú)法作出太多改進(jìn),于是目的變?yōu)橐源隧?xiàng)目作為理解Spring的一個(gè)跳板,與網(wǎng)上的一些模仿Spring的框架不同,本項(xiàng)目主要是針對(duì)注解形式
概述
項(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è)大的階段,
這只是大概的劃分,關(guān)于BeanPostProcessor等后置處理并沒(méi)有顯式的提及.
類(lèi)的設(shè)計(jì)
如果只想了解一個(gè)bean是怎么從生到死的,只需要一步步debug就好了,如果看不懂,就多debug幾遍.可是如果想實(shí)現(xiàn)一個(gè)類(lèi)似的容器,類(lèi)的設(shè)計(jì),職責(zé)的分配,接口的實(shí)現(xiàn)繼承必然是要了解的(除非你想幾個(gè)類(lèi)做完所有的事)
以下是DefaultListableBeanFactory的類(lèi)圖
是不是頂不住
我們?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的類(lèi),這時(shí)候我們需要給定的參數(shù)就從文件路徑變成了包路徑,我們只需要掃描這個(gè)包及其子包內(nèi)符合條件的類(lèi),并且將其轉(zhuǎn)化為BeanDefinition再注冊(cè)就好.執(zhí)行這個(gè)功能的是ClassPathBeanDefinitionScanner這個(gè)類(lèi).在這一步,就已經(jīng)和傳統(tǒng)的流程有所區(qū)別了,我們會(huì)傳入一個(gè)ResourceLoader去實(shí)現(xiàn)具體的掃描功能(即定位),但不會(huì)再有專(zhuān)門(mén)的類(lèi)去處理解析這一步
public interface Resource {File getFile();String getFilename();String getFilePath(); } //在最初設(shè)計(jì)的時(shí)候這個(gè)抽象類(lèi)似乎沒(méi)有用,但考慮到以后的擴(kuò)展,還是先放在這 public abstract class AbstractResource implements Resource {@Overridepublic String getFilename() {return getFile().getName();}@Overridepublic String getFilePath() {return getFile().getPath();} } //這就是最終我們實(shí)例化bean時(shí)用到的Resource類(lèi),在Spring中并沒(méi)有直接用,而是通過(guò)外觀模式集成了一下成為RootBeanDefinition public 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); } //此類(lèi)能夠?qū)崿F(xiàn)加載多個(gè)資源 public interface ResourcePatternResolver extends ResourceLoader {String CLASSPATH_ALL_URL_PREFIX = "classpath*:";List<? extends Resource> getResources(String location); }//這個(gè)類(lèi)就是正式用于掃描的類(lèi)了 public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {private final ResourceLoader resourceLoader;public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader){this.resourceLoader = resourceLoader;}@Overridepublic Resource getResource(String location) {return resourceLoader.getResource(location);} //在Spring中,是通過(guò)一層層方法的包裝完成包名到路徑的轉(zhuǎn)換再到每個(gè)文件的掃描再轉(zhuǎn)換為Resource,這里暫時(shí)就先一步到位,把具體實(shí)現(xiàn)放在工具類(lèi)里@Overridepublic 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è)類(lèi)里調(diào)用.
我們得到了Resource,如何獲得對(duì)應(yīng)的BeanDefinition?
先考慮這樣一個(gè)問(wèn)題,什么樣的類(lèi)可以被注冊(cè)BeanDefinition?
所以我們可以單獨(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{@Overridepublic 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ù)的類(lèi)型和數(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)字段值獲取
我們通過(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)行依賴(lài)查找,依賴(lài)注入的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),專(zhuān)門(mén)用一個(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不能借助容器,為了解決此類(lèi)問(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è)泛型與傳入的事件類(lèi)型的關(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());//判斷感興趣的事件類(lèi)型是否與傳入事件相同,或者是其父類(lèi)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)依賴(lài)的解決
循環(huán)依賴(lài)是指A依賴(lài)于B的同時(shí)B依賴(lài)于A,解決方法為實(shí)例化與初始化分離,如果只考慮一般情況的話用兩級(jí)緩存實(shí)際上就夠了,代碼優(yōu)化
實(shí)現(xiàn)簡(jiǎn)易AOP
如果從正統(tǒng)的AOP開(kāi)始的話,隨之而來(lái)的就是一堆概念,包括切點(diǎn),通知一類(lèi)
我們先看AOP要做什么
所以說(shuō)AOP的核心就是動(dòng)態(tài)代理,我們以Cglib為例來(lái)看看動(dòng)態(tài)代理要怎么用
Enhancer enhancer = new Enhancer(); //1. 為哪個(gè)類(lèi)進(jìn)行代理enhancer.setSuperclass(Buy.class);enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {//2. 為該類(lèi)的哪個(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,可不可以不分這些種類(lèi),就全寫(xiě)在一個(gè)或幾個(gè)類(lèi)里,當(dāng)然可以,Spring0.9就是這么做的,但發(fā)展到如今,早已采用了這種劃分方式.本項(xiàng)目也采用這種分類(lèi).
先從連接點(diǎn)說(shuō)起,如何確定到底在哪里實(shí)現(xiàn)功能增強(qiáng),無(wú)非是類(lèi)與方法兩個(gè)層次;
我們先定義ClassFilter與MethodMacther兩個(gè)接口
public interface ClassFilter {/*** 給定類(lèi)型是否匹配* @param clazz* @return*/boolean matches(Class< ? > clazz); } public interface MethodMatcher {/*** 對(duì)應(yīng)類(lèi)的對(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];@Overridepublic ClassFilter getClassFilter() {return null;}@Overridepublic MethodMatcher getMethodMatcher() {return this;}@Overridepublic 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類(lèi),也就是說(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)我們交由用戶(hù)去做
接下來(lái)就是整合成Advisor了
public interface Advisor {Advice getAdvice(); } public interface PointcutAdvisor extends Advisor{Pointcut getPointcut(); } public abstract class AbstractPointcutAdvisor implements PointcutAdvisor{private Advice advice;@Overridepublic 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);}@Overridepublic Pointcut getPointcut() {return pointcut;} }RegexMethodPointcutAdvisor就整合了PointCut以及Advice,通過(guò)他,我們就可以確定在何處做何種增強(qiáng).
現(xiàn)在的advisor可以完成檢驗(yàn)一個(gè)類(lèi)是否要被代理的功能,但是如果這個(gè)類(lèi)需要被代理,advisor卻無(wú)法保存這個(gè)類(lèi)的對(duì)應(yīng)信息
于是我們需要一個(gè)類(lèi)將advisor與對(duì)應(yīng)的代理類(lèi)結(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);} }上類(lèi)屬性中的TargetSource便是真正持有代理對(duì)象信息的類(lèi)
現(xiàn)在萬(wàn)事具備,只需要用Cglib去使用我們已經(jīng)持有的信息就可以創(chuàng)建出新的類(lèi)了
public class CglibAopProxy implements AopProxy{private final AdvisedSupport advised;public CglibAopProxy(AdvisedSupport advised) {this.advised = advised;}@Overridepublic Object getProxy() {Enhancer enhancer = new Enhancer();//1. 為哪個(gè)類(lèi)進(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;}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {CglibInvocation cglibInvocation = new CglibInvocation(method,objects,o,methodProxy);//2. 為該類(lèi)的哪個(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)該盡可能的給用戶(hù)以方便
于是我們需要一個(gè)Creator去把這一切都做好,他需要負(fù)責(zé)將Advice和PointCut組合成Advisor,再將Advisor與TargetSource組裝成AdvisedSupport,再將AdvisedSupport交給Cglib動(dòng)態(tài)代理,產(chǎn)生代理對(duì)象,而用戶(hù)只需要編寫(xiě)Advice以及切入點(diǎn)表達(dá)式即可
功能演示
屬性注入
困難及解決
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。?
總結(jié)
以上是生活随笔為你收集整理的模仿Spring实现一个类管理容器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 阿里云 AI 编辑部获 CCBN 创新奖
- 下一篇: 最佳实践|Spring Boot 应用如