容器
AnnotationConfigApplicationContext
组件添加(注册)
组件复制
组件注入
以上是IOC部分
AOP
声明式事务
一、组件注册
spring重要的是IOC控制反转和DI依赖注入,spring认为所有的组件都应该放在IOC容器中,然后组件之间的关系通过容器进行自动装配,也就是依赖注入。
总结概括:
1.包扫描+组件标注注解(@Conntroller/@Service/@Repository/@Component)[自己写的类]
2.@Bean[导入的第三方包里面的组件,也就是第一种方式以外的(自己创建一个组件,再@Bean]
3.@Import[快速给容器中导入一个组件]:
①@Import(要导入到容器中的组件):容器会自动注册这个组件,id默认是全类名;
②ImportSelector:返回需要导入的组件的全类名数组;
③ImportBeanDefinitionRegistrar:手动注册bean到容器中
4.使用spring提供的FactoryBean(工厂Bean):
①默认获取到的是工厂bean调用getObject创建的对象(而不是注册的工厂Bean)(这里的理解用工厂模式来理解);
②要获取工厂Bean本身,我们需要给id前面加一个&
1. @Configuration和@Bean
@Configuration:告诉spring这是一个配置类,加入IOC容器中,配置类==配置文件
@Bean:注册组件。默认的beanId是函数名,可以用value属性进行指定。
@Configuration
public class MyConfig {
@Bean
public Person person() {
return new Person("ZhangSan", 10);
}
}
加载配置类
public class MainTest {
public static void main(String[] args) {
//注解式开发 传入配置类的位置
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
//获取bean的名称
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println(name);
}
}
}
2. @ComponentScan和@ComponentScans
在原来的spring的配置文件中都会 <context:component-scan base-package=" "></context:component-scan>来进行包扫描
但是如果用注解就是@ComponentScan
例如@ComponentScan(value=“指定要扫描的包名”,excludeFilters={@Filter(type=FilterType.排除方式(例如按注解排除),class={注解名.class})
value:指定要扫描的包
excludeFilters=@Filter[],指定扫描的时候按什么规则排除哪些组件
includeFilters=@Filter[],指定扫描的时候只需要包含哪些组件
要让includeFilters生效,需要让useDefaultFilters=false
扫描com.student包下的组件,排除@Controller、@Service注解的类
@Configuration
@ComponentScan(value = "com.student", excludeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = {
Controller.class, Service.class})})
public class MyConfig {
@Bean
public Person person() {
return new Person("ZhangSan", 10);
}
}
只包含@Controller、@Service注解的类。(需要先禁用默认的过滤规则useDefaultFilters=false,因为默认的过滤规则是全部扫描)
@Configuration
@ComponentScan(value = "com.student",
useDefaultFilters = false,
includeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = {
Controller.class, Service.class})
})
public class MyConfig {
@Bean
public Person person() {
return new Person("ZhangSan", 10);
}
}
配置包扫描有哪些过滤规则
FilterType.ANNOTATION:按照注解(也就是标注了某一注解的类)
FilterType.ASSIGNABLE_TYPE:按照给定的类型(也就是具体的类)
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:使用正则指定
FilterType.CUSTOM:使用自定义的规则(也就是自己可以自定义一个Filter实现TypeFilter,然后返回true则容器中包含这些类,返回false则不包含这些类)
自定义TypeFilter规则:
MetadataReader:读取到的当前正在扫描的类的信息
MetadataReaderFactory:可以获取到其他任何类的信息
public class MyTypeFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 获取当前正在扫描类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前的资源信息(类的路径)
metadataReader.getResource();
String className = classMetadata.getClassName();
if(className.contains("er"))
return true;
return false;
}
}
@ComponentScans可以包含多个@ComponentScan
格式为
@ComponentScans(
value = {
@ComponentScan(value = "com.atguigu",includeFilters = {
@Filter(type = FilterType.CUSTOM,classes = {
MyTypeFilter.class})
},useDefaultFilters = false)
})
3. @Scope
设置组件作用域
可以取哪些范围
prototype(ConfigurableBeanFactory.SCOPE_PROTOTYPE ):多实例的:ioc容器启动并不会去3调用方法创建对象放在容器中,每次获取的时候才会调用方法创建对象
singleton(ConfigurableBeanFactory.SCOPE_SINGLETON):单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取都是直接从容器(map.get())中拿
以上两个的区别是是:只创建容器的时候&#