目录
注册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