javaBean类:
package cn.it.bean; /** * @author Admin * @create 2019-04-20-20:37 */ public class Person { private String name; /** * */ private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public Person() { } 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; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
bean.xml:
注册了一个Person类
@Test void XmlTest(){ ApplicationContext ioc = new ClassPathXmlApplicationContext("bean.xml"); Person bean = ioc.getBean(Person.class); System.out.println(bean); }
首先获取ioc容器,再从容器中拿到Person对象
配置类MainConfig
/** * 配置类 == 配置文件 * @author Admin * @create 2019-04-20-20:43 */ @Configuration //告诉spring这是一个配置类 public class MainConfig { //给容器中注册一个Bean,类型为返回值的类型,id默认是方法名作为id @Bean(value = "person") public Person person01(){ return new Person("张三",18); } }
1.@Configuration:告诉spring这是一个配置类
2.@Bean:给容器中注册一个Bean,类型为返回值的类型,id默认是方法名作为id
value:设置id
public class MainTest { @Test void test1(){ //通过配置类获取ioc容器 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); Person person = applicationContext.getBean(Person.class); System.out.println(person); //打印出当前ioc容器中的所有注册的bean的id String[] names = applicationContext.getBeanNamesForType(Person.class); for (String name : names) { System.out.println(name); } }
使用AnnotationConfigApplicationContext获取ioc容器,
创建添加了三层类,添加了注解@Controller,@Service,@Repository
@ComponentScan(value = "cn.it")
value:指定包名
开启包扫描后的再次打印容器中的组件名添加了注解的类全部被扫描进来了
自定义扫描
@ComponentScan(value = "cn.it", //指定要扫描哪些类 includeFilters = { //使用@Filter注解 @ComponentScan.Filter( type = FilterType.ANNOTATION,//类型 classes = {Controller.class, Service.class}//指定类 )} //禁用默认行为 ,useDefaultFilters = false )
excludeFilters:扫描时指定排除那些 ----->是一个Filter[]------>@Filter注解
includeFilters:扫描时指定扫描那些 ----->是一个Filter[]------>@Filter注解
注意:使用includeFilters时还是与配置文件一样,要禁用掉默认的扫描行为
使用useDefaultFilters = false属性来禁用
@Filter的type:
ANNOTATION:按照注解
ASSIGNABLE_TYPE:按照给定的类型
ASPECTJ:使用ASPECTJ表达式
REGEX:使用正则表达式
- CUSTOM:自定义规则
CUSTOM使用:
1.创建TypeFilter的实现类(实现match方法)
@Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return false; }
参数:
MetadataReader :读取到当前正在扫描的类的信息
方法:
MetadataReaderFactory: 可以获取到其他类的信息
自定义的过滤器,只扫描类名包含"er"的类:
package cn.it.config; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; /** * @author Admin * @create 2019-04-21-16:06 */ public class MyTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类的注解信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //当前正在扫描的类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类的资源信息 Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); //打印结果 System.out.println("当前类名:" + className); //类名包含er的返回true if (className.contains("er")) return true; else return false; } }
2.配置新的过滤规则:
@ComponentScan.Filter( type = FilterType.CUSTOM,//类型 classes = {MyTypeFilter.class}//自定义类 )}
打印结果:
1.打印的类名
2.扫描结果
有er的类全都扫描进ioc容器了
spring默认的Bean都是单实例的,不论获取多少次,拿到的都是同一个对象
@Test void IOCTest(){ AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig02.class); Person bean1 = ioc.getBean(Person.class); Person bean2 = ioc.getBean(Person.class); System.out.println("bean1与bean2是同一个吗?:"+(bean1 == bean2)); }
使用:@Scope注解,表明这个Bean是单实例还是多实例
Scope:
- prototype:多实例(是每一次获取是才调用方法去创建对象)
singleton:单实例(默认值)(ioc容器启动时就调用方法创建对象,保存在ioc容器中,每一次获取只是从ioc容器中取出同一个对象)
request:同一次请求创建一个实例
session:同一个session创建一个实例
给Bean添加上@Scope注解,开启多实例
@Configuration public class MainConfig02 { @Scope(value = "prototype") @Bean public Person person(){ return new Person("王五",23); } }
打印结果:
懒加载(@Lazy) :用于单实例的Bean,使单实例Bean在ioc容器启动时不创建,而是在第一次获取的时候创建
@Conditional:按照一定的条件进行判断,满足条件给容器中注册bean、
@Conditional( condition[] ):里面是放实现了Condition接口的实现类
Condition接口:
public interface Condition { boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2); }
ConditionContext :判断条件能使用上下文(环境)
public interface ConditionContext { // 获取Bean定义 BeanDefinitionRegistry getRegistry(); // 获取Bean工程,因此就可以获取容器中的所有bean ConfigurableListableBeanFactory getBeanFactory(); // environment 持有所有的配置信息 Environment getEnvironment(); // 资源信息 ResourceLoader getResourceLoader(); // 类加载信息 ClassLoader getClassLoader(); }
AnnotatedTypeMetadata :注释信息
1. @Import(要导入容器的组件)
@Configuration @Import(Color.class) public class MainConfig02 { @Bean("Tom") public Person person(){ return new Person("Tom",20); } @Bean("Alice") public Person person1(){ return new Person("Alice",25); } }
使用Import注解注册Color类
可以导入多个类
@Import(
{class1,class2,.....}
)
2.传入ImportSelector的实现类:返回需要导入容器的组件的全类名数组
创建实现了ImportSelector接口的类
public class MyImportSelector implements ImportSelector { //AnnotationMetadata:当前标注了@Import的类的所有注解信息 @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"cn.it.bean.Color","cn.it.bean.Red"}; } }
在@Import中加上自定义的类
@Configuration @Import(MyImportSelector.class) public class MainConfig02 { @Bean("Tom") public Person person(){ return new Person("Tom",20); } @Bean("Alice") public Person person1(){ return new Person("Alice",25); } }
结果:
自定义ImportSelector传入的2个全类名的类都注册到ioc容器中
3.传入 ImportBeanDefinitionRegistrar的实现类:手动注册到容器中
自定义实现类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { //判断容器中是否含有Tom和Alice boolean tom = beanDefinitionRegistry.containsBeanDefinition("Tom"); boolean alice = beanDefinitionRegistry.containsBeanDefinition("Alice"); //如果有给容器中注册一个Bob if(tom && alice){ RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class); beanDefinitionRegistry.registerBeanDefinition("Bob",beanDefinition); } } }
配置类引入MyImportBeanDefinitionRegistrar类:
@Configuration @Import({MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class MainConfig02 { @Bean("Tom") public Person person(){ return new Person("Tom",20); } @Bean("Alice") public Person person1(){ return new Person("Alice",25); } }
结果:
public interface FactoryBean
{ T getObject() throws Exception; Class> getObjectType(); boolean isSingleton(); }