Spring注解学习总结-老版本

总纲:
一:注解类:Configuration Scope Lazy Contional
二:注入bean的方式:
1、包扫描+组件标注注解(@Controller)
2、@Bean(可以主要用于第三方类库里面的组件,无法手动添加注解)
3、@Import(快速给容器中导入一个组件)
4、使用Spring提供的FactoryBean
三:bean生命周期管理 扩展Spring底层中对于BeanPostProcessor的使用 ApplicationContextAwareProcessor可以set进来当前的ioc容器 BeanValidationPostProcessor对于数据的校验
InitDestroyAnnotationBeanPostProcessor PostConstruct PreDestroy注解依赖于它
AutowiredAnnotationBeanPostProcessor Autowired为啥能够注入bean依赖于它
四:属性赋值 @Value,
-- 自动装配 @Autowired(先按照类型装配再按照名称装配 - 容器中多个组件不要乱写@Qualifier强制指定名称。Autowired可以指定不必须) @Parmry放到注解可以指定当前优先级高但小于Qualifier
-- JSR250 和 JSR350指定德注解@Resource和@Inject 这俩都是java规范
@Resource默认按照组件名称装配,可以指定name 不支持Qualifier Parmry 不支持可以指定不必须
@Inject 需要inject依赖 支持Parmry 不支持可以指定不必须
Autowired放置位置 1 set方法 2 构造器-只有一个有参构造器,参数位置可以省略 3 方法参数 4 属性 配置类注册bean德时候可以参数位置加上使用

1、配置类注解Configuration,可重入注解ComponentScan - value;excludeFilters、includeFilters(useDefaultFilters = false) 自定义Filter

------------------------------我是分割线--------------------------------------------------------------------------------

2、Scope指定bean的作用域 - 主要理解单实例(容器启动时加载bean)多实例(第一次获取时加载bean)

------------------------------我是分割线--------------------------------------------------------------------------------

3、Lazy 懒加载 - 针对于单实例
------------------------------我是分割线--------------------------------------------------------------------------------

4、Contional 按照条件注册bean condition(上下文,注释信息) 放在类上没有就近原则,对所有类都生效
// ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// h获取类加载器
ClassLoader classLoader = context.getClassLoader();
// 获取运行时环境
Environment environment = context.getEnvironment();
// 获取bean定义的注册类 -- 注册 异常 查询是否有bean的定义
BeanDefinitionRegistry registry = context.getRegistry();
------------------------------我是分割线--------------------------------------------------------------------------------

5、Import:
1 @Import(Color.class)
2 ImportSelector 导入一个选择器 实现接口注意不要返回null 数字值为全类名@Import({Color.class, MySelector.class})
3 ImportBeanDefinitionRegistrar
public class MyReject implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean b = registry.containsBeanDefinition("com.original.model.Blue");
BeanDefinition beanDefinition = new RootBeanDefinition("com.original.model.Red");
if (b) {
registry.registerBeanDefinition("red", beanDefinition);
}
}
}
4 FactoryBean -- 返回的bean名称为colorFactoryBean 获取bean类型为Color -- 如何获取我的ColorFactoryBean 通过获取bean名称获取时添加&符号
public class ColorFactoryBean implements FactoryBean {
// 返回一个color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
System.out.println("ColorFactoryBean... getObject");
return new Color();
}

        @Override
        public Class<?> getObjectType() {
            return Color.class;
        }

        // true 标识单实例
        @Override
        public boolean isSingleton() {
            return true;
        }
    }
    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
    -----
    @Test
    public void factoryTest(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig3.class);
        ourBeanName(applicationContext);
        Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");
        System.out.println(colorFactoryBean.getClass());
        Object colorFactoryBean1 = applicationContext.getBean("&colorFactoryBean");
        System.out.println(colorFactoryBean1.getClass());
    }

------------------------------我是分割线--------------------------------------------------------------------------------

6、bean的生命周期 xml配置方式可以指定init-method="" destroy-method="" -- 注意当指定成多实例时 spring不会在关闭容器时销毁bean,多实例创建的bean不被spring管理
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
applicationContext.close();
car constructor....
car ... init
car ... destroy
(1)@Bean注解指定@Bean(initMethod = "init", destroyMethod = "destroy") 对象创建完成,并赋值好,调用初始化方法
(2)通过实现接口InitializingBean, DisposableBean的方法
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat() {
System.out.println("cat constructor");
}

@Override
public void destroy() throws Exception {
    System.out.println("cat ...destroy");
}

@Override
public void afterPropertiesSet() throws Exception {
    System.out.println("cat...init");
}

}
(3)@PostConstruct jsr定义的注解 @PreDestroy
(4)接口BeanPostProcessor :bean的后置处理器;
在bean初始化之前进行一些操作 postProcessBeforeInitialization:在实例化之后初始化之前(InitializingBean、afterPropertiesSet、init-method)
postProcessAfterInitialization:在初始化之后
-- BeanPostProcessor 源码流程解析:调用栈 - 1 test方法
2 ioc容器构造器 refresh();刷新容器
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
3 refresh方法 初始化所有剩余的单实例对象
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
4 finishBeanFactoryInitialization 初始化所有单实例bean
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
5 getBean(beanName); doGetBean(name, null, null, false); 获取bean 获取不到则创建bean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
6 Object beanInstance = doCreateBean(beanName, mbdToUse, args);完之后创建好了bean
7 exposedObject = initializeBean(beanName, exposedObject, mbd);这个方法里面为后置处理器的调用 在方法调用前有个populateBean(beanName, mbd, instanceWrapper);
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
8 populateBean(beanName, mbd, instanceWrapper);为属性赋值
9 initializeBean中 invokeInitMethods为执行初始化方法 关注前后的applyBeanPostProcessorsBeforeInitialization applyBeanPostProcessorsAfterInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

	try {
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
10 获取到容器中所有的BeanPostProcessor 挨个执行postProcessBeforeInitialization 
  一旦方法返回null 跳出for循环,不会执行后面的BeanPostProcessor
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

------------------------------我是分割线--------------------------------------------------------------------------------
7 属性赋值
1 @Value注解在属性上 3种
1)基本数值
2)SpEl #{}
3)从当前运行环境种取${} xml通过<context:property-placeholder location="classpath:people.properties"/> 注解
@PropertySource(value = {"classpath:/people.properties"})加载到applicationContext.getEnvironment()
--@Value("zhangsan")
private String name;

-- @Value("#{30-2}")
private int age;
------------------------------我是分割线--------------------------------------------------------------------------------
8 自动装配

posted @ 2021-06-04 02:23  杨大德  阅读(73)  评论(0)    收藏  举报