Spring底层核心组件
BeanDefinition
BeanDefinition表示Bean定义,有很多属性用来描述Bean的特点:
-
class,表示Bean类型
-
scope,表示Bean作用域,单例或原型等
-
lazyInit:表示Bean是否是懒加载
-
initMethodName:表示Bean初始化时要执行的方法
-
destroyMethodName:表示Bean销毁时要执行的方法
-
还有很多…
定义Bean的方式主要分为两种:
-
申明式定义
1、 2、@Bean 3、@Component(@Service,@Controller)
-
编程式定义
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中 AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(User.class); beanDefinition.setScope("prototype"); // 设置作用域 beanDefinition.setInitMethodName("init"); // 设置初始化方法 beanDefinition.setLazyInit(true); // 设置懒加载 context.registerBeanDefinition("user", beanDefinition); System.out.println(context.getBean("user"));
BeanDefinitionReader
BeanDefinition读取器,虽然开发中用的很少,但是源码中用得很多
AnnotatedBeanDefinitionReader
把某个类转换为BeanDefinition,并且解析类上的注解
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(AppConfig.class);
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);
System.out.println(context.getBean("user"));
可以解析的注解:@Conditional、@Scope、@Lazy、@Primary、@DependsOn、 @Role、@Description
XmlBeanDefinitionReader
解析标签
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
System.out.println(context.getBean("user"));
ClassPathBeanDefinitionScanner
扫描器,可以进行扫描,扫描某个包路径,对扫描到的类进行解析
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.gax");
System.out.println(context.getBean("userService"));
BeanFactory
Bean工厂,负责创建Bean,并且提供获取Bean的 API
ApplicationContext就是BeanFactory的一种
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,
HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}
Hier服务器托管网archicalBeanFactory: 支持父子Bean工厂,子Bean工厂获取不到时,可以到父Bean工厂去获取
ListableBeanFactory: 展示Bean的名字、展示Bean的数量、统计的信息、拿某一个类型的Bean,类似列表的功能
EnvironmentCapable: 获取环境变量的功能
ApplicationEventPublisher: 事件发布的功能
MessageSource: 国际化的功能
ResourcePatternResolver: 获取某些资源、解析某些资源的功能
Spring源码中,BeanFactory接口非常重要的实现类: DefaultListableBeanFactory
ApplicationContext.getBean() 调用的就是 DefaultListableBeanFactory 的getBean()方法
DefaultListableBeanFactory 可以单独使用:
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanFactory.registerBeanDefinition("user", beanDefinition);
System.out.println(beanFactory.getBean("user"));
ApplicationContext
ApplicationContext是个接口,实际上也是一个BeanFactory,不过比BeanFactory 更加强大:
1、HierarchicalBeanFactory:拥有获取父BeanFactory的功能
2、ListableBeanFactory:拥有获取beanNames的功能
3、ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
4、EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)
5、ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)
6、MessageSource:拥有国际化功能
ApplicationContext两个重要的实现类:
1、AnnotationConfigApplicationContext
2、ClassPathXmlApplicationContext
国际化
定义一个MessageSource
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
ApplicationContext拥有国际化的功能,可以直接用
context.getMessage("test", null, new Locale("en_CN"))
资源加载
可以利用ApplicationContext获取某个文件的内容
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Resource resource = context.getResource("file://D:UserService.java");
System.out.println(resource.contentLength());
System.out.println(resource.getFilename());
Resource resource1 = context.getResource("https://www.baidu.com");
System.out.println(resource1.contentLength());
System.out.println(resource1.getURL());
Resource resource2 = context.getResource("classpath:spring.xml");
System.out.println(resource2.contentLength());
System.out.println(resource2.getURL());
Resource[] resources = context.getResources("classpath:com/gax/*.class");
for (Resource resource : resources) {
System.out.println(resource.contentLength());
System.out.println(resource.getFilename());
}
获取运行时环境
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Map systemEnvironment = context.getEnvironment().getSystemEnvironment();
System.out.println(systemEnvironment); //操作系统层面的环境变量
Map systemProperties = context.getEnvironment().getSystemProperties();
System.out.println(systemProperties); //运行java通过-D指定的环境变量
MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
System.out.println(propertySources); //最强大的,包含上面两种和PropertySources注解的变量
System.out.println(context.getEnvironment().getProperty("NO_PROXY")); //操作系统
System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding")); //jvm -D指定
System.out.println(context.getEnvironment().getProperty("gax")); //property里面的
事件发布
定义一个事件监听器
@Bean
public ApplicationListener applicationListener() {
return new ApplicationListener() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("接收到了一个事件");
}
};
}
发布一个事件
context.publishEvent("yeah");
类型转化
Spring提供了一些方便类型转化的技术
PropertyEditor
JDK中提供的类型转化工具类,使用示例:
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor
{
@Override
public void setAsText(String text) throws IllegalArgumentException
{
User user = new User();
user.setName(text);
this.setValue(user);
}
// 单独使用示例
public static void main(String[] args)
{
StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
propertyEditor.setAsText("11");
User value = (User)propertyEditor.getValue();
System.out.println(value);
System.out.println(value.getName());
}
}
输出:
com.gax.service.User@5a07e868
11
向Spring中注册PropertyEditor:
@Bean
public CustomEditorConfigurer customEditorConfigurer()
{
CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
Map, Class extends PropertyEditor>> propertyEditorMap = new HashMap();
// StringToUserPropertyEditor可以将String转化成User类型,
// 在Spring源码中,如果当前对象是String,而需要的类型是User,就会用该PropertyEditor做类型转化
propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);
customEditorConfigurer.setCustomEditors(propertyEditorMap);
return customEditorConfigurer;
}
// 示例代码
@Component
public class UserService
{
@Value("ccc")
private User user; //这里需要类型转换
public void test()
{
System.out.println(user);
}
}
// 测试
public class Test
{
public static void main(String[] args)
{
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
}
}
输出:(输出的是一个User,转换成功)
com.gax.service.User@17ed40e0
ConversionService
Spring中提供的类型转化服务,它比PropertyEditor更强大
public class StringToUserConverter implements ConditionalGenericConverter
{
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType)
{
return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
}
@Override
public Set getConvertibleTypes()
{
return Collections.singleton(new GenericConverter.ConvertiblePair(String.class, User.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType)
{
User user = new User();
user.setName((String)source);
return user;
}
}
// 单独使用
public class Test
{
public stati服务器托管网c void main(String[] args)
{
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringToUserConverter());
User value = conversionService.convert("1", User.class);
System.out.println(value);
}
}
向Spring中注册ConversionService:
@Bean
public ConversionServiceFactoryBean conversionService()
{
ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));
return conversionServiceFactoryBean;
}
TypeConverter
Spring提供更高级的转换类SimpleTypeConverter,可以支持上面两种
public class Test
{
public static void main(String[] args)
{
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
// DefaultConversionService conversionService = new DefaultConversionService();
// conversionService.addConverter(new StringToUserConverter());
// typeConverter.setConversionService(conversionService);
User value = typeConverter.convertIfNecessary("1", User.class);
System.out.println(value);
}
}
扩展:
// getBean指定类型转换
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = applicationContext.getBean("userService", UserService.class);
// 可以对应到Spring源码:AbstractBeanFactory#adaptBeanInstance
T adaptBeanInstance(String name, Object bean, @Nullable Class> requiredType) {
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// SimpleTypeConverter
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) { // 已经转换过了返回,没转换报错
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
OrderComparator
Spring所提供的一种比较器,有@Order注解、实现Ordered接口两种使用方式,通过指定的值进行比较或排序。
实现Ordered接口示例代码:
public class A implements Ordered
{
@Override
public int getOrder()
{
return 3;
}
@Override
public String toString()
{
return this.getClass().getSimpleName();
}
}
public class B implements Ordered
{
@Override
public int getOrder()
{
return 2;
}
@Override
public String toString()
{
return this.getClass().getSimpleName();
}
}
public class Main
{
public static void main(String[] args)
{
A a = new A(); // order=3
B b = new B(); // order=2
OrderComparator comparator = new OrderComparator();
System.out.println(comparator.compare(a, b)); // 1 (a>b,a();
list.add(a);
list.add(b);
// 按order值升序排序
list.sort(comparator);
System.out.println(list); // B,A
}
}
输出:
1
[B, A]
Spring还提供了一个OrderComparator的子类: AnnotationAwareOrderComparator,它支持用@Order来指定order值
@Order(3)
public class A
{
@Override
public String toString()
{
return this.getClass().getSimpleName();
}
}
@Order(2)
public class B
{
@Override
public String toString()
{
return this.getClass().getSimpleName();
}
}
public class Main
{
public static void main(String[] args)
{
A a = new A(); // order=3
B b = new B(); // order=2
AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
System.out.println(comparator.compare(a, b)); // 1
List list = new ArrayList();
list.add(a);
list.add(b);
// 按order值升序排序
list.sort(comparator);
System.out.println(list); // B,A
}
}
输出:
1
[B, A]
// 关键源码:AnnotationAwareOrderComparator#findOrder
protected Integer findOrder(Object obj) {
// 先获取Ordered接口中getOrder()方法返回的数值
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
// 如果没有实现Ordered接口,则获取@Order注解中指定的值
return findOrderFromAnnotation(obj);
}
BeanPostProcessor
BeanPostProcess表示Bean的后置处理器,可以定义一个或多个BeanPostProcessor
@Component
public class GaxBeanPostProcessor implements BeanPostProcessor
{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
{
if ("userService".equals(beanName))
{
System.out.println("初始化前");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
{
if ("userService".equals(beanName))
{
System.out.println("初始化后");
}
return bean;
}
}
BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自定义的逻辑,当然还可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分Bean)。
我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程
BeanFactoryPostProcessor
Bean工厂的后置处理器,和BeanPostProcessor类似。
BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。
@Component
public class GaxBeanFactoryPostProcessor implements BeanFactoryPostProcessor
{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
{
System.out.println("加工beanFactory");
}
}
FactoryBean
上面提到,可以通过BeanPostPorcessor来干涉Spring创建Bean的过程。但是如果我们想一个Bean完完全全由我们来创造,也是可以的,比如通过FactoryBean:
@Component
public class GaxFactoryBean implements FactoryBean
{
@Override
public Object getObject()
{
return new UserService();
}
@Override
public Class> getObjectType()
{
return UserService.class;
}
}
// 测试
public class Test
{
public static void main(String[] args) throws IOException
{
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
Object gaxFactoryBean = applicationContext.getBean("gaxFactoryBean");
Object gaxFactoryBean2 = applicationContext.getBean("&gaxFactoryBean");
Object gaxFactoryBean3 = applicationContext.getBean("&&&&&&gaxFactoryBean");
System.out.println(gaxFactoryBean);
System.out.println(gaxFactoryBean2);
System.out.println(gaxFactoryBean3);
}
}
输出:
com.gax.service.UserService@6e3c1e69
com.gax.GaxFactoryBean@5f150435
com.gax.GaxFactoryBean@5f150435
注意:通过这种方式创造出来的UserService的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入。
通过@Bean也可以生成一个对象作为Bean,那么和FactoryBean的区别是什么呢?
其实在很多场景下他俩是可以替换的,但是站在原理层面来说的,区别很明显,@Bean定义的Bean是会经过完整的Bean生命周期的。
ExcludeFilter和IncludeFilter
ExcludeFilter表示排除过滤器,IncludeFilter表示包含过滤器
// 扫描com.gax这个包下面的所有类,但是排除UserService类
// 也就是就算类上面有@Component注解也不会成为Bean
@ComponentScan(value = "com.gax", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = UserService.class)})
public class AppConfig {
}
// 就算UserService类上没有@Component注解,也会被扫描成为一个Bean
@ComponentScan(value = "com.gax", includeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = UserService.class)})
public class AppConfig {
}
FilterType分为:
1、ANNOTATION:是否包含某个注解
2、ASSIGNABLE_TYPE:是否是某个类
3、ASPECTJ:是否符合某个Aspectj表达式
4、REGEX:是否符合某个正则表达式
5、CUSTOM:自定义
Spring内部怎么支持@Component注解扫描的?
在Spring的扫描逻辑中,默认会添加一个AnnotationTypeFilter给includeFilters,表示默认情况下 Spring扫描过程中会认为类上有@Component注解的就是Bean。
// ClassPathScanningCandidateComponentProvider#registerDefaultFilters
protected void registerDefaultFilters() {
// 注册@Component对应的AnnotationTypeFilter
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
... ...
}
MetadataReader、ClassMetadata、 AnnotationMetadata
在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数 据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。
public interface MetadataReader {
/**
* Return the resource reference for the class file.
*/
Resource getResource();
/**
* Read basic class metadata for the underlying class.
*/
ClassMetadata getClassMetadata();
/**
* Read full annotation metadata for the underlying class,
* including metadata for annotated methods.
*/
AnnotationMetadata getAnnotationMetadata();
}
// 类的元数据
public interface ClassMetadata {
/**
* Return the name of the underlying class.
*/
String getClassName();
/**
* Return whether the underlying class represents an interface.
*/
boolean isInterface();
/**
* Return whether the underlying class represents an annotation.
* @since 4.1
*/
boolean isAnnotation();
/**
* Return whether the underlying class is marked as abstract.
*/
boolean isAbstract();
/**
* Return whether the underlying class represents a concrete class,
* i.e. neither an interface nor an abstract class.
*/
default boolean isConcrete() {
return !(isInterface() || isAbstract());
}
... ...
}
// 注解元数据
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
/**
* Get the fully qualified class names of all annotation types that
* are present on the underlying class.
* @return the annotation type names
*/
default Set getAnnotationTypes() {
return getAnnotations().stream()
.filter(MergedAnnotation::isDirectlyPresent)
.map(annotation -> annotation.getType().getName())
.collect(Collectors.toCollection(LinkedHashSet::new));
}
/**
* Determine whether an annotation of the given type is present on
* the underlying class.
* @param annotationName the fully qualified class name of the annotation
* type to look for
* @return {@code true} if a matching annotation is present
*/
default boolean hasAnnotation(String annotationName) {
return getAnnotations().isDirectlyPresent(annotationName);
}
/**
* 可以判断类下面有没有指定注解,比如说判断一个类下面有没有@Bean修饰的方法
* Determine whether the underlying class has an annotation that is itself
* annotated with the meta-annotation of the given type.
* @param metaAnnotationName the fully qualified class name of the
* meta-annotation type to look for
* @return {@code true} if a matching meta-annotation is present
*/
default boolean hasMetaAnnotation(String metaAnnotationName) {
return getAnnotations().get(metaAnnotationName,
MergedAnnotation::isMetaPresent).isPresent();
}
... ...
}
MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。
public class Test
{
public static void main(String[] args) throws IOException
{
SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
// 构造一个MetadataReader
MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.gax.service.UserService");
// 得到一个ClassMetadata,并获取了类名
ClassMetadata classMetadata = metadataReader.getClassMetadata();
System.out.println(classMetadata.getClassName());
// 获取一个AnnotationMetadata,并获取类上的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
for (String annotationType : annotationMetadata.getAnnotationTypes())
{
System.out.println(annotationType);
}
}
}
输出:
com.gax.service.UserService
org.springframework.stereotype.Component
注意:SimpleMetadataReader去解析类时,使用的ASM技术。
ASM简述:把类当成普通文件,通过字节流读出来,如果符合字节码规范,就根据字节码的格式获取类的信息
为什么要使用ASM技术?
Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了 ASM技术
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
目录 编辑 一、数据库的基本操作 1.1展示所有数据库 1.2切换数据库 1.3创建数据库 1.4删除数据库 1.5显示数据库信息 1.5.1显示数据库信息 1.5.2显示数据库详情 二、数据库表的基本操作 2.1创建表的操作 2.1.1创建普通hive表(…