准备
java版本:java8
spring boot版本:2.1.10
构建spring boot项目,添加lombok依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
1、组件注册
a. @Configuration和@Bean给容器中注册组件
构建实体类Person.class
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
private Integer age;
}
注入组件
@Configuration // 告诉spring这是一个配置类
public class MainConfig {
/**
*给spring容器注册一个bean,默认bean的id为方法名称,即“mike”
*/
@Bean
public Person mike() {
return new Person("麦克", 21);
}
@Bean
public Person jack() {
return new Person("杰克", 13);
}
}
测试
@Test
public void PersonBeanTest() {
// 获取MainConfig.class的上下文环境
ApplicationContext context =
new AnnotationConfigApplicationContext(MainConfig.class);
// 若MainConfig.class中存在多个Person的bean会抛出异常
// Person mike = context.getBean(Person.class); // error
// System.out.println(mike);
Person mike = context.getBean("mike", Person.class); // 根据id获取bean
System.out.println(mike); // Person(name=麦克, age=21)
String[] beanNames = context.getBeanNamesForType(Person.class); // 获取bean名称列表
System.out.println(Arrays.toString(beanNames)); // [mike, jack]
}
b. @ComponentScan自动扫描组件
//value指定扫描包的路径
@ComponentScan(value = "com.smallbear.springcoredemo.config")
public class ScanConfig {
}
测试
@Test
public void componentScanTest() {
ApplicationContext context =
new AnnotationConfigApplicationContext(ScanConfig.class);
String[] beanNames = context.getBeanDefinitionNames(); // 获取扫描到的组件名称
for (String s : beanNames) {
System.out.println(s); // scanConfig、mainConfig、mike、jack,还有几个spring自身的组件
}
}
c. @Scope设置组件作用域
在MainConfig.class
中添加组件
//默认为单实例(singleton),程序启动的时候便会调用该方法将生成的对象实例注入到ioc容器中
@Scope
@Bean
public Person tom() {
System.out.println("注册组件tom");
return new Person("汤姆", 41);
}
//多实例模式,ioc容器启动时并不会立即创建对象,每次获取的时候会调用该方法创建一个对象
@Scope("prototype")
@Bean
public Person snow() {
System.out.println("注册组件snow");
return new Person("雪诺", 31);
}
测试
@Test
public void scopeTest() {
ApplicationContext context =
new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("获取组件...");
Person tom1 = context.getBean("tom", Person.class);
Person tom2 = context.getBean("tom", Person.class);
System.out.println("tom1==tom2: " + (tom1 == tom2));
Person snow1 = context.getBean("snow", Person.class);
Person snow2 = context.getBean("snow", Person.class);
System.out.println("snow1==snow2: " + (snow1 == snow2));
}
/*
print result:
注册组件tom
获取组件...
tom1==tom2: true
注册组件snow
注册组件snow
snow1==snow2: false
*/
d. @Import快速的给容器导入一个组件
创建一个实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Color {
private String name;
}
在MainConfig.java
类上添加注解@Import({Color.class})
便成功将Color.class
注册到容器中,组件名称为com.smallbear.springcoredemo.entity.Color
。
e. @Conditional按照条件注册bean
实现Condition
接口
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
System.out.println(property); // Windows 7
return property != null && property.contains("Windows");
}
}
在MainConfig.class
注入bean
/**
*若操作系统是Windows系统,则注入bill组件
*/
@Conditional(WindowsCondition.class)
@Bean
public Person bill() {
return new Person("比尔盖茨", 65);
}
f. 使用FactoryBean注册组件
public class ColorFactoryBean implements FactoryBean<Color> {
@Override
public Color getObject() throws Exception {
return new Color("red");
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
/**
* 是否是单实例, FactoryBean接口的默认返回true
*/
@Override
public boolean isSingleton() {
return true;
}
}
在MainConfig.class
中注入bean
@Bean
public ColorFactoryBean colorFactoryBean() {
return new ColorFactoryBean();
}
测试
@Test
public void factoryBeanTest() {
ApplicationContext context =
new AnnotationConfigApplicationContext(MainConfig.class);
//容器中注入的是colorFactoryBean组件,但获取的时候返回的是color对象
Color color = context.getBean("colorFactoryBean", Color.class);
System.out.println(color.getName()); // red
}
g. 小结
容器中常用的注册bean的方法
1、组件标注注解(@Controller
, @Service
, @Component
, @Repository
等)
2、@Bean
3、@Import
4、使用FactoryBean
工厂
2、bean的生命周期
a. @Bean指定初始化和销毁方法
@Data
public class Car {
private String name;
private BigDecimal price;
public Car() {
System.out.println("car constructor...");
}
public Car(String name, BigDecimal price) {
this.name = name;
this.price = price;
System.out.println(this.name + " constructor...");
}
public void init() {
System.out.println(name + " init...");
}
public void destroy() {
System.out.println(name + " destroy...");
}
}
/**
* bean的生命周期(由容器来管理):创建---初始化---销毁
* 可以自定义初始化和销毁方法
*/
@Configuration
public class MainConfigOfLifeCycle {
/**
*指定容器的初始化和销毁方法
* 1、单实例
* 初始化:对象创建完成时调用
* 销毁:容器关闭时调用
*/
@Bean(initMethod = "init", destroyMethod = "destroy")
public Car benz() {
return new Car("奔驰", BigDecimal.valueOf(200000));
}
/**
* 2、多实例
* 初始化 获取bean时触发
* 销毁 不会主动销毁
*/
@Scope("prototype")
@Bean(initMethod = "init", destroyMethod = "destroy")
public Car BYD() {
return new Car("比亚迪", BigDecimal.valueOf(12000));
}
}
测试
@Test
public void BenzTest() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器启动完成...");
Car BYD = context.getBean("BYD", Car.class);
context.close();
}
/*
奔驰 constructor...
奔驰 init...
容器启动完成...
比亚迪 constructor...
比亚迪 init...
奔驰 destroy...
*/
b. InitializingBean和DisposableBean
通过InitializingBean
和DisposableBean
接口实现bean初始化和销毁方法
public class Cat implements DisposableBean, InitializingBean {
@Override
public void destroy() throws Exception {
System.out.println("cat destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat init...");
}
}
c. @PostConstruct和@PreDestroy
通过@PostConstruct
和@PreDestroy
注解实现bean初始化和销毁方法
public class Dog {
@PostConstruct
public void init() {
System.out.println("cat init...");
}
@PreDestroy
public void destroy() {
System.out.println("dog destroy...");
}
}
d. BeanPostProcessor
BeanPostProcessor
Bean初始化后置处理器
/**
* Bean初始化后置处理器
*/
@Component
@ComponentScan("com.smallbear.springcoredemo")
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
*初始化之前执行
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "->before init...");
return bean;
}
/**
* 初始化之后执行
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "->after init...");
return bean;
}
}
测试
@Test
public void beanPostProcessorTest() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(MyBeanPostProcessor.class);
Car BYD = context.getBean("BYD", Car.class);
context.close();
}
/*
print result部分内容:
比亚迪 constructor...
BYD->before init...
比亚迪 init...
BYD->after init..
*/
3. 自动装配
构建新的spring boot项目
a. @Autowired和@Qualifier
@Autowired:自动注入:
1、优先按照类型去容器中查找对应的组件
2、如果有过个相同类型的组件,再将属性名作为id去容器中寻找
@Qualifier:指定需要装配的组件的id
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Pet {
private String name;
}
@Configuration
@ComponentScan("com.smallbear.springcoredemo2")
public class MainConfigOfAutoWired {
//注册name为duck、cat、mouse的组件,
// 由于米奇和杰瑞组件的名称相同,杰瑞组件没有注册到容器中
@Bean
public Pet duck() {
return new Pet("唐老鸭");
}
@Bean("cat")
public Pet cat() {
return new Pet("汤姆");
}
@Bean
public Pet mouse() {
return new Pet("米奇");
}
@Primary
@Bean("mouse")
public Pet mouse2() {
return new Pet("杰瑞");
}
}
@Service
public class PetService {
@Autowired
private Pet duck; // 注入唐老鸭
@Qualifier("cat") // 指定需要装配的组件的id
@Autowired
private Pet pet; // 此处注入id为cat的组件(汤姆)
@Autowired
private Pet mouse; // 注入米奇
public void printDuck() {
System.out.println(duck.getName());
}
public void printCat() {
System.out.println(pet.getName());
}
public void printMouse() {
System.out.println(mouse.getName());
}
}
@Test
public void test01() {
ApplicationContext context =
new AnnotationConfigApplicationContext(MainConfigOfAutoWired.class);
PetService petService = context.getBean("petService", PetService.class);
String[] petNames = context.getBeanNamesForType(Pet.class);
System.out.println(Arrays.toString(petNames)); // [duck, cat, mouse]
petService.printDuck(); // 唐老鸭
petService.printCat(); // 汤姆
petService.printMouse(); // 米奇
}
b. 支持@Resource(java规范的注解)
c. 方法、构造器位置的自动装配
@Component
public class MyPet {
private Pet cat;
private Pet mouse;
@Autowired // 注入汤姆
public MyPet(Pet cat) {
this.cat = cat;
}
@Autowired // 注入米奇
private void setMouse(Pet mouse) {
this.mouse = mouse;
}
}
网友评论