“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第3篇文章,点击查看活动详情”
1.BeanDefinition
主要作用是用来封装bean的信息:类型,是否是懒加载,是否是单例等等。
在spring中BeanDefinition是一个接口,它会有各种各样的实现类,这里我们只需要知道,它就是用来封装bean基本信息的就行了。
2.声明式定义bean 编程式定义bean,
声明式定义bean: @Bean @Component 或者是xml 中的bena标签
编程式定义bean: 就是使用代码来注册bean生命bean的一些信息:单例,懒加载,等等。
例如:
public static void main(String[] args) {
//ApplicationContext applicationContext = new ApplicationContext(UserService.class);
//编程式
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(UserService.class);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(UserService.class);
context.registerBeanDefinition("userService",beanDefinition);
//
UserService userService = (UserService)context.getBean("userService");
userService.test();
}
}
3. 读取器:AnnotatedBeanDefinitionReader
这个类是beanDefinition 读取器,可以将类封装成一个beanDefinition ,然后放入到spring容器当中变成一个bena。
public class User {
public void test(){
System.out.println("123123123");
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
//注册一个bean
reader.register(User.class);
User user = (User)context.getBean("user");
user.test();
}
}
我们看上面的代码,user类是没有加注解的,正常情况下是不可能加载到spring容器当中的。使用AnnotatedBeanDefinitionReader 的 register()方法就可以将User类变成beanDefinition然后放到spring容器当中。 我们看下这里面的源码:
reader.register(User.class);
/**
* Register one or more component classes to be processed.
* <p>Calls to {@code register} are idempotent; adding the same
* component class more than once has no additional effect.
* @param componentClasses one or more component classes,
* e.g. {@link Configuration @Configuration} classes
*/
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
//创建一个beanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//处理类上的注解信息
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
我们可以看到这个注册方法中创建了一个beanDefinition:
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
然后就是对这个beanDefinition 进行各种处理,以上就是这个类的主要作用。
我们看 AnnotationConfigApplicationContext 中的构造方法:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
可以看到AnnotationConfigApplicationContext()方法中创建了一个 AnnotatedBeanDefinitionReader。并且register(componentClasses)方法中使用的就是这里创建的AnnotatedBeanDefinitionReader的注册方法。
4. 扫描器:ClassPathBeanDefinitionScanner
一般在创建spring容器的时候,会传一个配置类,配置类上会配置有扫描路径,spring就会知道要扫描哪个包下面的类。
那么在创建spring容器的时候不传配置类,可以通过 ClassPathBeanDefinitionScanner 的scan 方法传一个包路径,与传配置类的效果是一样的。
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.xl.service");
User user = (User)context.getBean("user");
user.test();
}
}
5.GenericBeanDefinition 及其子类
ClassPathBeanDefinitionScanner和AnnotatedBeanDefinitionReader都会生成beanDefinition但是他们生成的类型是不一样的。
AnnotatedBeanDefinitionReader 对应的:AnnotatedGenericBeanDefinition
ClassPathBeanDefinitionScanner 对应的:ScannedGenericBeanDefinition
这两个beanDefinition都继承了GenericBeanDefinition。
6.ApplicationContext 和 BeanFactory
对比下可以看到,ApplicationContext 继承了除beanFactory外的很多接口,beanFactory 只是一个单纯的接口。
- ApplicationContext 拥有BeanFactory的功能:创建bean 获取bean
- ApplicationContext 拥有事件发布(ApplicationEventPublisher),国际化(MessageSource),获取环境变量(EnvironmentCapable),获取某些资源(ResourcePatternResolver)的功能,
- BeanFactory 只拥有创建bena,获取bean的功能。
如果只是创建bean 和获取bean,那么使用beanFactory就可以了。
public class Test {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanFactory.registerBeanDefinition("user",beanDefinition);
User user = (User)beanFactory.getBean("user");
user.test();
}
}
DefaultListableBeanFactory 是beanFactory的一个实现类。AnnotationConfigApplicationContext中使用的就这个实现类。
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
@Nullable
private ResourceLoader resourceLoader;
private boolean customClassLoader = false;
private final AtomicBoolean refreshed = new AtomicBoolean();
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
}
以上源码只是一部分,可以看到AnnotationConfigApplicationContext继承了GenericApplicationContext,GenericApplicationContext中的beanFactory类型是DefaultListableBeanFactory。
从上面这个类图可以看到,DefaultListableBeanFactory实现了很多接口,这些接口每个都有不同的功能,下面列举了一部分。
AliasRegistry:可以给bean起别名。
SingletonBeanRegistry:单例bean注册的功能。
BeanDefinitionRegistry:注册beanDefinition的功能。
HierarchicalBeanFactory:获取父beanFactory的功能。
ListableBeanFactory:判断是否包含这个beanDefinition,获取beanDefinition的名字 等功能
AutowireCapableBeanFactory:自动注入的beanFactory
7.MetadataReader ClassMetadata AnnotationMetadata
ClassMetadata :类的元数据信息。可以通过它来获取类的很多信息:父类的名字,接口的名字等等。
AnnotationMetadata: 注解的元数据信息。主要是获取一个类上面注解的相关信息.
它们与beanDefinition是不一样的,beanDefinition 是获取不到父类的名字,接口的名字的。所以,ClassMetadata 和 AnnotationMetadata 相比较beanDefinition 可以获取类的信息要全的多。
public class Test {
public static void main(String[] args) throws IOException {
SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
//创建一个metadataReader
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader("com.xl.service.User");
//获取一个classMetadata
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取类名
System.out.println(classMetadata.getClassName());
//获取内部类名
System.out.println(classMetadata.getMemberClassNames()[0]);
//获取一个annotationMetadata
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取类上注解的信息
for (String type:annotationMetadata.getAnnotationTypes()){
System.out.println(type);
}
}
}
8.includeFilters 和 excludeFilters
excludeFilters排除,typ 属性可以指定类,注解等。 classes属性要指定排除的具体类或者注解。指定之后,spring是不对排除的注解或者类做任何处理的。
includeFilters包含,如果一个类没有加注解那么它是不会成为bean(一般情况下),但是它被includeFilters指定包含了,也会被sprig加载容器中成为bean。 以下这个这个两个的基本用法。
@ComponentScan(value = "com.xl.service",
includeFilters = {@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = User.class
)})
public class AppConfig {
}
@ComponentScan(value = "com.xl.service",
excludeFilters = {@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = User.class
)})
public class AppConfig {
}
public class User {
public void test(){
System.out.println("123123123");
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
User user = (User)context.getBean("user");
user.test();
}
}
在spring中使用includeFilters, ClassPathScanningCandidateComponentProvider 类下registerDefaultFilters()方法中。 spring默认会添加一个includeFilters,只要在扫描的时候发现一个类上面带有@Component,它就会认为符合includeFilters,这个类就是一个bean,它就会解析这个类生成一个beanDefinition.
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
9.FactoryBean
一个类实现了这个接口,那么在getBean的时候返回的是getObject()方法返回的bean。如果想获取原来的bean,getBean("&lynnFactoryBean")在名字前面加& 就可以。 并且这个返回的这个bean只经历初始化后这么一个过程,并没有经历完成的bean的生命周期。 以下是测试代码
@Component("user")
public class LynnFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
@Component
public class LynnPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("user")){
System.out.println("qian "+bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("user")){
System.out.println("hou: "+bean);
}
return bean;
}
}
@ComponentScan(value = "com.xl.service")
public class AppConfig {
}
@Aspect
@Component
public class LynnAspect {
@Before("execution(public void com.xl.service.User.test())")
public void before(JoinPoint joinPoint){
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//这个返回的是User类型的bean
System.out.println(context.getBean("user"));
//这个返回的是 LynnFactoryBean类型的bean
//System.out.println(context.getBean("&lynnFactoryBean"));
}
}
以上大致就是spring框架中一些基本概念,如有笔误还请指正。