做海報(bào)設(shè)計(jì)的圖片網(wǎng)站有哪些廣州seo推薦
BeanDefinition
BeanDefinition表示Bean定義,BeanDefinition中存在很多屬性用來描述一個(gè)Bean的特點(diǎn).比如:
- beanClass:表示Bean類型
- scope:表示Bean作用域,單例/原型等
- lazyInit:表示Bean是否懶加載
- initMethodName:表示Bean初始化時(shí)要執(zhí)行的方法
- destoryMethodName:表示Bean銷毀時(shí)要執(zhí)行的方法
- …
再Spring中,我們經(jīng)常會(huì)通過以下幾種方式來定義Bean:
<bean/>
- @Bean
- @Component/@Service/@Controller
這些可以稱之為 申明式定義Bean.
還可以 編程式定義Bean,那就是直接通過BeanDefinition
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 生成一個(gè)BeanDefinition對(duì)象AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();// 設(shè)置beanClass為User.classbeanDefinition.setBeanClass(User.class);// 注冊(cè)到ApplicationContext中context.registerBeanDefinition("user",beanDefinition);System.out.println(context.getBean("user"));
}// com.fanqiechaodan.entity.User@2034b64c
還可以通過BeanDefinition設(shè)置一個(gè)Bean的其他屬性
// 設(shè)置作用域
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 設(shè)置初始化方法
beanDefinition.setInitMethodName("init");
// 設(shè)置懶加載
beanDefinition.setLazyInit(true);
和申明式事務(wù),編程式事務(wù)類似,通過<bean/>
,@Bean,@Component等申明方式所定義的Bean,最終都會(huì)被Spring解析為對(duì)應(yīng)的BeanDefinition對(duì)象,并放入Spring容器中.
BeanDefinitionReader
BeanDefinitionReader(BeanDefinition讀取器),這些BeanDefinitionReader在使用Spring時(shí)用的少,但在Spring源碼中用的多,相當(dāng)于Spring的基礎(chǔ)設(shè)置
AnnotatedBeanDefinitionReader
可以直接把某個(gè)類轉(zhuǎn)換為BeanDefinition,并解析該類上的注解
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(context);// 將User.class解析為BeanDefinitionbeanDefinitionReader.register(User.class);System.out.println(context.getBean("user"));
}
注意:它能解析的注解是:@Conditional,@DependsOn,@Description,@Lazy,@Primary,@Role,@Scope
XmlBeanDefinitionReader
可以解析<bean/>
標(biāo)簽
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(context);// 返回注冊(cè)Bean的數(shù)量int i = beanDefinitionReader.loadBeanDefinitions("spring.xml");System.out.println(context.getBean("user"));
}
ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner是掃描器,但是它的作用與BeanDefinitionReader類似,它可以進(jìn)行掃描,掃描某個(gè)包路徑,對(duì)掃描的類進(jìn)行解析,比如:掃描到的類如果存在@Component注解,那么就會(huì)把這個(gè)類解析為一個(gè)BeanDefinition.
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);ClassPathBeanDefinitionScanner beanDefinitionScanner = new ClassPathBeanDefinitionScanner(context);beanDefinitionScanner.scan("com.fanqiechaodan");System.out.println(context.getBean("userService"));
}
BeanFactory
BeanFactory表示Bean工廠,所以很明顯,BeanFactory會(huì)負(fù)責(zé)創(chuàng)建Bean,并且提供獲取Bean的API.
而ApplicationContext是BeanFactory的一種,在Spring源碼中,是這么定義的:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {// ...
}
首先,在Java中,接口時(shí)可以 多繼承 的,我們發(fā)現(xiàn)ApplicationContext繼承了ListableBeanFactory和HierarchicalBeanFactory,而ListableBeanFactory和HierarchicalBeanFactory都繼承至BeanFactory,等同ApplicationContext繼承了BeanFactory,ApplicationContext也是BeanFactory的一種,擁有BeanFactory支持的所有功能,不過ApplicationContext比BeanFactory更加強(qiáng)大,ApplicationContext還繼承了其他接口,也就表示ApplicationContext還擁有其他的功能.比如MessageSource(國(guó)際化),ApplicationEventPublisher(事件發(fā)布)等等.
在Spring源碼實(shí)現(xiàn)中,當(dāng)我們new一個(gè)ApplicationContext時(shí),其底層會(huì)new一個(gè)BeanFactory出來,當(dāng)使用ApplicationContext的某些方法時(shí),比如getBean(),底層調(diào)用的是BeanFactory的getBean().
在Spring源碼中,BeanFactory接口存在一個(gè)非常重要的實(shí)現(xiàn)類:DefaultListableBeanFactory.所以我們可以直接來使用 DefaultListableBeanFactory,而不用使用ApplicationContext的某個(gè)實(shí)現(xiàn)類
public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();beanDefinition.setBeanClass(User.class);beanFactory.registerBeanDefinition("user",beanDefinition);System.out.println(beanFactory.getBean("user"));
}
DefaultListableBeanFactory是非常強(qiáng)大的,支持很多功能,可以通過查看DefaultListableBeanFactory的類繼承實(shí)現(xiàn)結(jié)構(gòu)來看
它實(shí)現(xiàn)了很多接口,表示它擁有很多功能:
- AliasRegistry:支持別名功能,一個(gè)名字可以對(duì)應(yīng)多個(gè)別名
- BeanDefinitionRegistry:可以注冊(cè),保存,移出,獲取某個(gè)BeanDefinition
- BeanFactory:Bean工廠,可以根據(jù)某個(gè)Bean的名字/類型/別名獲取某個(gè)Bean對(duì)象
- SingletonBeanRegistry:可以注冊(cè),獲取某個(gè)單例Bean
- SimpleAliasRegistry:它是一個(gè)類,實(shí)現(xiàn)了AliasRegistry接口中所定義的功能,支持別名
- ListableBeanFactory:在BeanFactory的基礎(chǔ)上,增加了其他功能,可以獲取所有BeanDefinition的beanNames,可以根據(jù)某個(gè)類型獲取對(duì)應(yīng)的beanNames,可以根據(jù)某個(gè)類型獲取{類型:對(duì)應(yīng)的Bean}的映射關(guān)系
- HierarchicalBeanFactory:在BeanFactory的基礎(chǔ)上,增加了獲取父BeanFactory的功能
- DefaultSingletonBeanRegisty:它是一個(gè)類,實(shí)現(xiàn)了SingletonBeanRegistry接口,擁有了直接注冊(cè),獲取某個(gè)單例Bean的功能
- ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基礎(chǔ)上,添加了設(shè)置父BeanFactory,類加載器(表示可以指定某個(gè)類加載器進(jìn)行類的加載),設(shè)置Spring EL表達(dá)式解析器(表示可以解析EL表達(dá)式),設(shè)置類型轉(zhuǎn)化服務(wù)(表示可以進(jìn)行類型轉(zhuǎn)化),可以添加BeanPostprocessor(表示支持Bean的后置處理器),可以合并BeanDefinition,可以銷毀某個(gè)Bean等等功能
- FactoryBeanRegistrySupport:支持了FactoryBean的功能
- AutowireCapableBeanFactory:直接繼承了BeanFactory,在BeanFactory的基礎(chǔ)上,支持創(chuàng)建Bean的過程中能對(duì)Bean進(jìn)行自動(dòng)裝配
- AbstractBeanFactory:繼承了FactoryBeanRegistrySupport,實(shí)現(xiàn)了ConfigurableBeanFactory,這個(gè)BeanFactory的功能已經(jīng)很全面了,但是不能自動(dòng)裝配和獲取beanNames
- ConfigurableListableBeanFactory:繼承了ListableBeanFactory,AutowireCapableBeanFactory,ConfigurableBeanFactory
- AbstractAutowireCapableBeanFactory:繼承了AbstractBeanFactory,實(shí)現(xiàn)了AutowireCapableBeanFactory擁有了自動(dòng)裝配的功能
- DefaultListableBeanFactory:直接或間接的繼承/實(shí)現(xiàn)以上所有類或接口.所以DefaultListableBeanFactory的功能很強(qiáng)大
ApplicationContext
ApplicationContext是個(gè)接口,實(shí)際上也是一個(gè)BeanFactory,不過比BeanFactory更加強(qiáng)大,比如:
- HierarchicalBeanFactory:擁有獲取父BeanFactory的功能
- ListableBeanFactory:擁有獲取beanNames的功能
- ResourcePatternResolver:資源加載器,可以一次性獲取多個(gè)資源(文件資源等等)
- EnvironmentCapable:可以獲取運(yùn)行時(shí)環(huán)境,沒有設(shè)置運(yùn)行時(shí)環(huán)境功能
- ApplicationEventPublisher:擁有廣播事件的功能,沒有添加事件監(jiān)聽的功能
- MessageSource:擁有國(guó)際化功能
ApplicationContext有兩個(gè)比較重要的實(shí)現(xiàn)類:
- AnnotationConfigApplicationContext
- ClassPathXmlApplicationContext
AnnotationConfigApplicationContext
- ConfigurableApplicationContext:繼承了ApplicationContext接口,增加了事件監(jiān)聽器,添加BeanFactoryPostProcessor,設(shè)置Environment,獲取ConfigurableListableBeanFactory等功能
- AbstractApplicationContext:實(shí)現(xiàn)了ConfigurableApplicationContext接口
- GenericApplicationContext:繼承了AbstractApplicationContext,實(shí)現(xiàn)了BeanDefinitionRegistry接口,擁有了所有ApplicationContext的功能,并且可以注冊(cè)BeanDefinition,這個(gè)類內(nèi)置了一個(gè)DefaultListableBeanFactory屬性
- AnnotationConfigRegistry:可以單獨(dú)注冊(cè)某個(gè)類為BeanDefinition,可以處理該類上的@Configuration注解@Bean注解,同時(shí)可以掃描
- AnnotationConfigApplicationContext:繼承了GenericApplicationContext,實(shí)現(xiàn)了AnnotationConfigRegistry接口,擁有了以上所有的功能
ClassPathXmlApplicationContext
它也是繼承了AbstractApplicationContext,但是相對(duì)于AnnotationConfigApplicationContext而言,功能沒有AnnotationConfigApplicationContext強(qiáng)大,比如不能注冊(cè)BeanDefinition
國(guó)際化
先定義一個(gè)MessageSource
@Bean
public MessageSource messageSource() {ResourceBundleMessageSource res = new ResourceBundleMessageSource();res.setBasename("en_CN");res.setDefaultEncoding("UTF-8");return res;
}
en_CN.properties
test=測(cè)試
有了這個(gè)Bean,可以在任意想要進(jìn)行國(guó)際化的地方使用MessageSource,同時(shí)因?yàn)锳pplicationContext繼承了MessageSource,也擁有國(guó)際化的功能
public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(context.getBean("messageSource"));System.out.println(context.getMessage("test", null, new Locale("en_CN")));
}// 測(cè)試
資源加載
ApplicationContext還擁有資源加載的功能
public static void main(String[] args) throws IOException {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Resource userService = context.getResource("file://C:\\devspace\\fanqiechaodan-spring\\src\\main\\java\\com\\fanqiechaodan\\service\\UserService.java");System.out.println(userService.contentLength());System.out.println(userService.getFilename());System.out.println();Resource baidu = context.getResource("https://www.baidu.com/");System.out.println(baidu.contentLength());System.out.println(baidu.getURL());System.out.println();Resource spring = context.getResource("classpath:spring.xml");System.out.println(spring.contentLength());System.out.println(spring.getURL());System.out.println();Resource[] resources = context.getResources("classpath:com/fanqiechaodan/entity/*.class");for (Resource resource : resources) {System.out.println(resource.contentLength());System.out.println(resource.getURL());}
}// 213
// UserService.java
//
// 2443
// https://www.baidu.com/
//
// 513
// file:/C:/devspace/fanqiechaodan-spring/target/classes/spring.xml
//
// 296
// file:/C:/devspace/fanqiechaodan-spring/target/classes/com/fanqiechaodan/entity/Address.class
// 672
// file:/C:/devspace/fanqiechaodan-spring/target/classes/com/fanqiechaodan/entity/User.class
獲取運(yùn)行時(shí)環(huán)境
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();System.out.println(systemEnvironment);System.out.println();Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();System.out.println(systemProperties);System.out.println();MutablePropertySources propertySources = context.getEnvironment().getPropertySources();System.out.println(propertySources);System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
}
事件發(fā)布
先定義一個(gè)事件監(jiān)聽器
@Bean
public ApplicationListener applicationListener() {return event -> System.out.println("接收到一個(gè)事件");
}
在發(fā)布事件
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);context.publishEvent("aaa");
}
類型轉(zhuǎn)化
在Spring源碼中,有可能需要把String轉(zhuǎn)成其他類型,所以在Spring源碼中提供了一些技術(shù)來更方便的做對(duì)象的類型轉(zhuǎn)化,關(guān)于類型轉(zhuǎn)化Spring有很多應(yīng)用.
PropertyEditor
這其實(shí)是JDK中提供的類型轉(zhuǎn)化工具類
public class String2UserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {@Overridepublic void setAsText(String text) throws IllegalArgumentException {User user = new User();user.setName(text);this.setValue(user);}
}public static void main(String[] args) {String2UserPropertyEditor editor = new String2UserPropertyEditor();editor.setAsText("testName");User user = (User) editor.getValue();System.out.println(user.getName());
}
如何向Spring中注冊(cè)PropertyEditor:
@Bean
public CustomEditorConfigurer customEditorConfigurer(){CustomEditorConfigurer editorConfigurer = new CustomEditorConfigurer();Map<Class<?>, Class<? extends PropertyEditor>> map = new HashMap<>();// 表示String2UserPropertyEditor可以將String轉(zhuǎn)換為User// 在Spring源碼中,如果發(fā)現(xiàn)當(dāng)前對(duì)象是String,需要的類型為User// 就會(huì)使用String2UserPropertyEditor來做類型轉(zhuǎn)化map.put(User.class, String2UserPropertyEditor.class);editorConfigurer.setCustomEditors(map);return editorConfigurer;
}
假設(shè)現(xiàn)在有以下Bean:
@Service
public class UserService {@Value("test")private User user;public void test(){System.out.println(user.getName());}
}
使用@Value可以完成對(duì)User的賦值
ConversionService
Spring中提供的類型轉(zhuǎn)化服務(wù),它比PropertyEditor更強(qiáng)大
public class String2UserConverter implements ConditionalGenericConverter {@Overridepublic boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);}@Overridepublic Set<ConvertiblePair> getConvertibleTypes() {return Collections.singleton(new ConvertiblePair(String.class, User.class));}@Overridepublic Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {User user = new User();user.setName((String) source);return user;}
}public static void main(String[] args) {DefaultConversionService conversionService = new DefaultConversionService();conversionService.addConverter(new String2UserConverter());User user = conversionService.convert("testName", User.class);System.out.println(user.getName());
}
如何向Spring中注冊(cè)ConversionService
@Bean
public ConversionServiceFactoryBean conversionServiceFactoryBean(){ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();conversionServiceFactoryBean.setConverters(Collections.singleton(new String2UserConverter()));return conversionServiceFactoryBean;
}
TypeConverter
整合了PropertyEditor和ConversionService的功能,是Spring內(nèi)部用的
public static void main(String[] args) {SimpleTypeConverter simpleTypeConverter = new SimpleTypeConverter();// 整合PropertyEditor// simpleTypeConverter.registerCustomEditor(User.class,new String2UserPropertyEditor());// 整合ConversionServiceDefaultConversionService conversionService = new DefaultConversionService();conversionService.addConverter(new String2UserConverter());simpleTypeConverter.setConversionService(conversionService);User test = simpleTypeConverter.convertIfNecessary("test", User.class);System.out.println(test.getName());
}
OrderComparator
OrderComparator是Spring所提供的一種比較器,可以用來根據(jù)@Order注解或?qū)崿F(xiàn)Ordered接口來執(zhí)行值進(jìn)行比較,從而可以進(jìn)行排序
@Data
public class A implements Ordered {@Overridepublic int getOrder() {return 1;}}@Data
public class B implements Ordered {@Overridepublic int getOrder() {return 0;}}public static void main(String[] args) {A a = new A();B b = new B();OrderComparator orderComparator = new OrderComparator();System.out.println(orderComparator.compare(a,b));System.out.println();List list = new ArrayList<>();list.add(a);list.add(b);// 按order值升序排序list.sort(orderComparator);System.out.println(list);
}// 1
//
// [B(), A()]
另外,Spring中還提供了一個(gè)OrderComparator的子類:AnnotationAwreOrderComparator,它支持用@Oder來指定order值
@Data
@Order(1)
public class A {}@Data
@Order(0)
public class B {}public static void main(String[] args) {A a = new A();B b = new B();OrderComparator orderComparator = new OrderComparator();System.out.println(orderComparator.compare(a,b));System.out.println();List list = new ArrayList<>();list.add(a);list.add(b);// 按order值升序排序list.sort(orderComparator);System.out.println(list);
}// 1
//
// [B(), A()]
BeanPostProcessor
BeanPostProcessor表示Bean后置處理器
@Component
public class BeanPostProcessorDemo implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)){System.out.println("userService初始化前");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)){System.out.println("userService初始化后");}return bean;}
}
一個(gè)BeanPostProcessor可以在任意一個(gè)Bean的初始化之前以及初始化之后去額外的做一些用戶自定義的邏輯,當(dāng)然,我們可以通過判斷beanName來進(jìn)行針對(duì)性處理(針對(duì)某個(gè)Bean或某部分Bean)
我們可以通過定義BeanPostProcessor來干涉Spring創(chuàng)建Bean的過程.
BeanFactoryPostProcessor
BeanFactoryPostProcessor表示Bean工廠的后置處理器,其實(shí)和BeanPostProcessor類似,BeanPostProcessor是干涉Bean的創(chuàng)建過程,BeanFactoryPostProcessor是干涉BeanFactory的創(chuàng)建過程.
@Component
public class BeanFactoryProcessorDemo implements BeanFactoryPostProcessor {/*** 可以對(duì)beanFactory進(jìn)行加工** @param beanFactory* @throws BeansException*/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("加工beanFactory");}
}
FactoryBean
我們可以通過BeanPostProcessor來干涉Bean創(chuàng)建的過程,如果想要一個(gè)Bean完全由我們來創(chuàng)建同樣是可以的.
@Component
public class FactoryBeanDemo implements FactoryBean {@Overridepublic Object getObject() throws Exception {return new UserService();}@Overridepublic Class<?> getObjectType() {return UserService.class;}
}
通過上面這段代碼,我們自己創(chuàng)建了一個(gè)UserService.并且它將成為Bean.但是通過這種方式創(chuàng)建的Bean.只會(huì)經(jīng)過 初始化后,其他Spring的生命周期是不會(huì)經(jīng)過的,比如依賴注入.而通過@Bean/@Service等等注解定義的Bean是會(huì)經(jīng)過完整的Bean生命周期的.
ExcludeFilter和IncludeFilter
這兩個(gè)Filter是Spring掃描過程中用來過濾的.ExcludeFilter表示 排除過濾器,IncludeFilter表示 包含過濾器.
/*** 掃描com.fanqiechaodan這個(gè)包下的所有類* 但是排除UserService即使它上面有@Component/@Service也不會(huì)注冊(cè)成Bean*/
@ComponentScan(value = "com.fanqiechaodan",excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)})
public class AppConfig {}
/*** 掃描com.fanqiechaodan這個(gè)包下的所有類* 包含UserService即使它上面沒有@Component/@Service也會(huì)注冊(cè)成Bean*/
@ComponentScan(value = "com.fanqiechaodan",includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)})
public class AppConfig {}
FilterType分為:
- ANNOTATION:表示是否包含某個(gè)注解
- ASSIGNABLE_TYPE:表示是否是某個(gè)類
- ASPECTJ:表示是否符合某個(gè)Aspectj表達(dá)式
- REGEX:表示是否符合某個(gè)正則表達(dá)式
- CUSTOM:自定義
MetadataReader,ClassMetadata,AnnotationMetadata
在Spring中需要去解析類的信息,比如類名,類中的方法,類上的注解,這些都可以稱之為類的元數(shù)據(jù),所以Spring對(duì)類的元數(shù)據(jù)做了抽象,并提供了一些工具類.
MetadataReader表示類的元數(shù)據(jù)讀取器,默認(rèn)實(shí)現(xiàn)類為 SimpleMetadataReader
public static void main(String[] args) throws IOException {SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();// 構(gòu)造一個(gè)MetadataReaderMetadataReader metadataReader = metadataReaderFactory.getMetadataReader("com.fanqiechaodan.service.UserService");// 得到了一個(gè)ClassMetadata,并獲取類名ClassMetadata classMetadata = metadataReader.getClassMetadata();System.out.println(classMetadata.getClassName());// 獲取一個(gè)AnnotationMetadata,并獲取類上的注解信息AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();for (String annotationType : annotationTypes) {System.out.println(annotationType);}
}