Spring源码学习(一)

目录

注册Bean的方法

@Bean

@Bean有关的注解

@ComponentScan

@Scope

 @Lazy

 @Conditional

@Import


注册Bean的方法

注册bean的方法有两种:JavaConfig和Xml方式

Xml方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
 		http://www.springframework.org/schema/beans/spring-beans.xsd"
	   default-autowire="byName" default-lazy-init="false">
	<bean id="person" class="myTest.beanTest.Person">
		<property name="uuid" value="123"></property>
	</bean>
</beans>
public void loadByXml() {
		AbstractApplicationContext aac = new ClassPathXmlApplicationContext("beans.xml");
		Person person = (Person) aac.getBean("person");
		System.out.println(person);
		aac.close();
	}

javaConfig方式(bean名字为方法名)

@Configuration
public class PersonConfig {
	@Bean
	public Person person(){
		Person person = new Person();
		person.setUuid(UUID.randomUUID().toString());
		return person;
	}
}
@org.junit.Test
	public void loadByAnnotation(){
		AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(PersonConfig.class);
		Person person = (Person) acc.getBean("person");
		System.out.println(person);
        aac.close();
	}

这里在看@Congratulations源码时发现,@Congratulations和@Component是一样的

查找资料得知,虽然Component注解也会当做配置类,但是并不会为其生成CGLIB代理Class,具体示例查看(81条消息) @Component和@Configuration作为配置类的差别_一号搬砖手的博客-CSDN博客_component和configuration的区别

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

	/**
	 * Explicitly specify the name of the Spring bean definition associated with the
	 * {@code @Configuration} class. If left unspecified (the common case), a bean
	 * name will be automatically generated.
	 * <p>The custom name applies only if the {@code @Configuration} class is picked
	 * up via component scanning or supplied directly to an
	 * {@link AnnotationConfigApplicationContext}. If the {@code @Configuration} class
	 * is registered as a traditional XML bean definition, the name/id of the bean
	 * element will take precedence.
	 * @return the explicit component name, if any (or empty String otherwise)
	 * @see AnnotationBeanNameGenerator
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

@Bean

//这两个属性是一样的,可以通过任意一个为Bean指定名字
@AliasFor("name")
	String[] value() default {};
@AliasFor("value")
	String[] name() default {};
//通过这个属性指定bean的初始化方法,在bean实例化及复制后执行
String initMethod() default "";
//通过这个属性指定bean的在bean生命周期完成(容器close)后执行
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
//在Person中加入Bean的初始化和销毁方法
public void myInitMethod(){
		System.out.println("bean初始化");
	}
public void myDestoryMethod(){
		System.out.println("bean生命周期结束");
	}
//为Bean指定初始化和销毁方法
@Bean(value = "myBean",initMethod = "myInitMethod",destroyMethod = "myDestoryMethod")
public Person person(){
		Person person = new Person();
		person.setUuid(UUID.randomUUID().toString());
		return person;
	}

@Bean有关的注解

@PostConstract(可以用来在Spring Bean初始化之后完成一些特定的操作,如初始化本地缓存)

@PreDestory( 在发布容器关闭事件之后,在执行Bean的destroy方法之前执行,可以用来做一些善后的操作,如关闭连接,记录日志,清空缓存等)

常用来影响Servlet的生命周期

@ComponentScan

value用来指定扫描的包

//扫描service包及其子包
@ComponentScan(value = "com.lh.service")

basePackageClasses用来扫描类所在的包

//扫描UserService所在包的组件
@ComponentScan(basePackageClasses ={UserService.class})

includeFilters自定义扫描时的规则

//扫描指定包下含有Service和Controller注解的组件,注意要将useDefaultFilters设为false
@ComponentScan(includeFilters = {
		@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class, Controller.class})
},useDefaultFiltersuser = false)

excludeFilters自定义扫描时不扫描的部分

扫描指定包下的组件时不扫描UserService类以及带有@Service注解的组件
@ComponentScan(excludeFilters = {
		@ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE,classes = {UserService.class),
		@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class})
},useDefaultFilters = false)

@Scope

指定Bean的作用域

Spring的Bean作用域有四种:    SCOPE_PROTOTYPE: 多实例,每次获取,都会生成一个新实例    SCOPE_SINGLETON: 单实例,多次获取到的都是一个实例    SCOPE_REQUEST: web中,每次请求会生成一个实例    SCOPE_SESSION: web中,同一个会话中多次获取到的是同一个实例.
public void loadByAnnotation(){
		AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(PersonConfig.class);
		Person person = (Person) acc.getBean("person");
		Person person1 = (Person) acc.getBean("person");
		System.out.println(person==person1);
		acc.close();
	}

当Scope的value指定为SCOPE_SINGLETON时,getBean得到的是同一个实例

当Scope指定为SCOPE_PROTYPR时,getBean得到的是两个不同的实例

 通过测试还可以发现当Scope指定为SCOPE_PROTYPR时并没有执行destroy方法,可以得知当使用 init-method 和 destroy-method 的时候,使用 prototype 时 Spring 不会负责销毁容器对象。

 @Lazy

Lazy表示懒加载如果标注,默认为true,即在使用时候才去创建并完成Bean的初始化

AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(PersonConfig.class);
//输出结果为空
//只有在加入acc.getBean("person")后,才会开始初始化Bean;

 @Conditional

conditional注解中为一个实现了Condition的类,类中实现了matches()方法,返回一个boolean值,当boolean值为true时才创建Bean

public class ConditionImpl implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		return false;
	}
}

返回false时候getBean()方法报错,找不到对应的Bean

@Import

用于快速给容器导入一个Bean

public class ImportTest {
	@Bean
	public void method(){
		System.out.println("创建methodBean");
	}
}
//通过@Import(ImportTest.class)快速导入一个Bean

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值