使用Spring注解注册Bean
给容器中注册组件:
1.包扫描+类注解 @Component @Controller @Service @Repository等
2.使用@Bean
3.使用Import
1.直接指定类.class
2.实现ImportSelector接口的子类,会注入返回数组中所有的类
3.实现ImportBeanDefinitionRegistrar接口的子类,其子类方法中包含可以直接注入Bean的对象
注册一个Bean
1.创建一个实体类
*/
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.添加配置类 并直接注入Bean
@Configuration //配置类注解
public class BeanTest {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);
//获取指定类型所有bean的id名列表
String [] persons = applicationContext.getBeanNamesForType(Person.class);
//遍历输出名字 (java8)
Arrays.asList(persons).forEach(System.out::println);
}
@Bean //当前方法返回值的对象会注入到spring容器中
public Person person(){
return new Person("张三",18);
}
@Bean //bean的id默认是方法名
public Person person1(){
return new Person("李四",20);
}
@Bean("wangwu") //当然也可以直接指定id名
public Person person2(){
return new Person("王五",14);
}
}
2.2.1 扫描指定包内的Bean
@Controller
public class BookController {
}
@Service
public class BookService {
}
@Repository
public class BookDao {
}
@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.springannotation")
public class TestBean {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
//获取容器中所有bean
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.asList(names).forEach(System.out::println);
}
}
2.2.2 扫描指定包内的Bean 并过滤
//1.去掉指定注解类型的Bean
@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.spring_annotation"
//去掉指定类型的Bean
,excludeFilters = {
@ComponentScan.Filter(
//指定需要过滤的类型(ANNOTATION,ASSIGNABLE_TYPE,ASPECTJ,REGEX,CUSTOM)
type = FilterType.ANNOTATION,
value = {Controller.class, Service.class}
)
}
)
public class TestBean {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
//获取容器中所有bean
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.asList(names).forEach(System.out::println);
}
}
2.2.3只获取指定注解类型的Bean
@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.spring_annotation"
,includeFilters = {
@ComponentScan.Filter(
//指定需要过滤的类型(ANNOTATION,ASSIGNABLE_TYPE,ASPECTJ,REGEX,CUSTOM)
type = FilterType.ANNOTATION,
value = {Controller.class, Service.class}
)
}
// 当需要使用includeFilters需要将 useDefaultFilters置为false ,否则includeFilters不起作用
,useDefaultFilters = false
)
public class TestBean {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
//获取容器中所有bean
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.asList(names).forEach(System.out::println);
}
}
2.2.4只获取指定类型的Bean
@Configuration
@ComponentScan(value = "com.lx.spring_annotation"
,includeFilters = {
//ASSIGNABLE_TYPE:指定类的类型 只获取BookService类型的类
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {BookService.class})
//ANNOTATION:注解的类型
,@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class})
}
,useDefaultFilters = false
)
public class TestBean {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
//获取容器中所有bean
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.asList(names).forEach(System.out::println);
}
}
2.2.5.获取自定义过滤规则
//自定义过滤规则
class MyTypeFilter implements TypeFilter {
//MetadataReader:当前扫描类的的信息
//MetadataReaderFactory:可以获取到其他任何类的信息
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前扫描类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前类的加载信息
Resource resource = metadataReader.getResource();
//获取当前扫描类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
System.out.println(classMetadata.getClassName());
//例如类名包含"er"
return classMetadata.getClassName().contains("er");
}
}
@Configuration
//扫描指定的包
@ComponentScan(value = "com.lx.spring_annotation.bean02"
,includeFilters = {
//CUSTOM:用户自定义类型
@ComponentScan.Filter(type = FilterType.CUSTOM,value = {MyTypeFilter.class})
}
,useDefaultFilters = false
)
public class TestBean {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestBean.class);
//获取容器中所有bean
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.asList(names).forEach(System.out::println);
}
}
3.1 对象的作用域及懒加载
@Configuration
public class BeanTest01 {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest01.class);
System.out.println("初始化结束!");
Person p1 = applicationContext.getBean("zhangsan",Person.class);
Person p2 = applicationContext.getBean("zhangsan",Person.class);
System.out.println(p1 == p2);//单例时每次获取的对象相同,在初始化时就创建对象
Person p3 = applicationContext.getBean("lisi",Person.class);
Person p4 = applicationContext.getBean("lisi",Person.class);
System.out.println(p3 == p4);//多例时每次获取对象不同,并且只有在获取对象时,才调用创建方法
System.out.println("第一次获取王五");//初始化不会创建对象
Person p5 = applicationContext.getBean("wangwu",Person.class);
}
//默认是单例的
// @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
@Bean("zhangsan")
public Person person(){
//当作用域为singletion 时,初始化时就会创建对象,每次获取对象是同一个
System.out.println("开始创建对象:张三");
return new Person("张三",12);
}
//取值为prototype时为多例
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean("lisi")
public Person person1(){
//当作用域为prototype时,在从ioc容器中获取对象时才会创建,每次获取对象都会新建
System.out.println("开始创建对象:李四");
return new Person("李四",13);
}
//延迟加载
@Lazy
@Bean("wangwu")
public Person person2(){
//初始化不会调用次方法
System.out.println("开始创建对象:王五");
return new Person("王五",12);
}
}
4.给定条件创建对象(springboot底层大量使用)
@Configuration
public class BeanTest02 {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest02.class);
ConfigurableEnvironment environment = applicationContext.getEnvironment();//获取系统变量
System.out.println(environment.getProperty("os.name"));//获取系统名
Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);//获取所有的Person
System.out.println(beansOfType);
}
//判断当前Bean是否需要添加到容器中,需要传入Condition的子类
@Conditional({LinuxCondition.class})
@Bean
public Person linux(){
return new Person("linux",100);
}
@Conditional({WindowsCondition.class})
@Bean
public Person windows(){
return new Person("windows",100);
}
}
class LinuxCondition implements Condition {
//context :获取当前上下文信息
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();//获取环境变量
return environment.getProperty("os.name").toLowerCase().contains("linux");
}
}
class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();//获取环境变量
return environment.getProperty("os.name").toLowerCase().contains("windows");
}
}
使用@Import导入类(可以是)到容器中
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotationMetadata;
import java.awt.print.Book;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Scanner;
import java.util.zip.ZipEntry;
/**
* 创建人:游林夕/2019/7/13 20 12
*/
@Configuration
//加载类到ioc容器中,id是类的全限定名
//如果类是ImportSelector的子类,就会加载selectImports方法返回的类数组
//如果类是ImportBeanDefinitionRegistrar的子类,在registerBeanDefinitions方法中就可以直接注册Bean
@Import({Date.class,ImportSelectorImpl.class,ImportBeanDefinitionRegistrarImpl.class})
public class BeanTest03 {
public static void main(String [] args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest03.class);
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.asList(names).forEach(System.out::println);
}
}
class ImportSelectorImpl implements ImportSelector{
@Override
//AnnotationMetadata对象可以获取到调用此方法的类所有注解的信息
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"java.awt.print.Book"};
}
}
class ImportBeanDefinitionRegistrarImpl implements ImportBeanDefinitionRegistrar{
@Override
//AnnotationMetadata对象可以获取到调用此方法的类所有注解的信息
//BeanDefinitionRegistry:可以获取到Bean定义的对象,可以自己添加Bean,删除Bean
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean b = registry.containsBeanDefinition("java.util.Date");//判断容器中是否有Date
boolean b1 = registry.containsBeanDefinition("java.awt.print.Book");
if (b && b1){
//Bean的注册信息
RootBeanDefinition definition = new RootBeanDefinition(ArrayList.class);
registry.registerBeanDefinition("list",definition);
}
}
}