@Configuration : 配置类 == 配置文件,告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu",excludeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})
@ComonentScan value : 指定要扫描的包(这个注解可以定义多个)
excludeFilters = Filter[] : 指定扫描的时候按照什么规则排除那些组件
includeFilters = Filter[] : 指定扫描的时候只需要包含那些组件
useDefaultFilters = false : 表示去掉默认扫描
FilterType.ANNOTATION : 按照注解类型 例如 : Controller.class
FilterType.ASSIGNABLE_TYPE : 按照给定的类型 例如 : UserService.class
FilterType.ASPECTJ : 使用ASPECTJ表达式
FilterType.REGEX : 使用正则指定
FilterType.CUSTOM : 使用自定义规则

自定义规则需要实现TypeFilter接口
public class MyTypeFilter implements TypeFilter {
/**
metadataReader : 读取到的当前正则扫描的类的信息
metadataReaderFactory : 可以获取到其他任何类的信息
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
// 获取当前类注解的信息
AnnotationMetadata annotationMetadate = metadataReader.getAnnontationMetadata();
// 获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
// 获取这个类名
String className = classMetadata.getClassName();
// 自定义匹配规则
if(className.contains("er")) {
return true;
}
return false;
}
}

@ComponentScans(
value {
@ComponentScan(value="com.atguigu",excludeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
}, useDefaultFilters = false)
}
) : 里面可以定义多个@ComponentScan

@Bean : 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id

@Scope("") : 表示这个对象或者这个bean的创建作用域范围(调整作用域).
prototype : 多实例的,ioc容器时并不会调用方法创建对象放在容器中.每次获取的时候才会调用方法创建对象.
singleton : 单实例的(默认值),ioc容器启动会调用方法创建对象放到ioc容器中.以后每次获取就是直接从容器(map.get())中拿.
request : 同一次请求创建一个实例
session : 同一个session创建一个实例

@Lazy : 懒加载
单实例bean,默认在容器启动的时候创建对象.
懒加载: 容器启动不创建对象,第一次调用(获取)Bean创建对象,并初始化.

@Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean(可以放在@Bean上,或者类上)
例如 :
//放在类上统一设置
// 类中组件统一设置,满足当前条件,这个类中配置的所有bean注册才能生效.
@Conditional({WindowsCondition.class})
@Configuration

//实现接口Condition
public class LinuxCondition implements Condition {
/**

*/
public boolean matchs(CondititContext context, AnnotatedTypeMetadata metadada) {
// 是否linux系统
// 1. 能获取到ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 2.获取类加载器
ClassLoader classLoader = context.getClassLoader();
// 3.获取当前环境信息
Environment environment = context.getEnvironment();
// 4.获取到bean定义的注册类(可以判断容器中的bean注册情况,也可以给容器中注册bean)
BeanDefinitionRegistry registry = context.getRegistry();
// 判断容器中是否包含bean
boolean definition = registry.containsBeanDefinition("persion");

String property = environment.getProperty("os.name");
if (property.contains("linux")){
return true;
}
return false;
}

}

// 获取bean名称
String[] namesForType = applicatinContext.getBeanNamsForType();
// 动态获取环境变量的值,获取容器运行环境例如 : windows,liunx
ConfigurableEnvironment environment = applicationContext.getEnvironment();
// 获取操作系统的名称
String property = environment.getProperty("os.name");

给容器中注册组件 :
1 : 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
2 : @Bean[导入的第三方包里面的组件]
3 : @Import[快速给容器中导入一个组件]
1) : @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是组件的全类名(也可以导入多个组件)
2) : ImportSelector : 返回需要导入的组件的全类名数组.
3) : ImportBeanDefinitionRegistrar : 手动注册Bean到容器中
4 : 使用Spring提供的FactoryBean(工厂Bean)
1) : 默认获取到的是工厂bean调用getObject创建的对象
2) : 要获取工厂Bean本身,我们需要给id前面加一个&
&colorFactoryBean

@Import(要导入到容器中的组件 例如 : Color.class) : 方在类上,导入组件,容器中就会自动注册这个组件,id默认是组件的全类名(也可以导入多个组件)
(2) ImportSelector : 返回需要导入的组件的全类名数组.
例如 :
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
// 返回值,就是导入到容器中的组件全类名
// AnnotationMetadata : 当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 方法不要返回null值
return new String[];
}
}
@Import({Color.class,Red.class,MyImportSelector.class})
(3) ImportBeanDefinitionRegistrar : 手动注册Bean到容器中
例如 :
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
// AnnotationMetadata : 当前类的注解信息
// BeanDefinitionRegistry : BeanDefinitionRegistry注册类;
// 把所有需要添加到容器中的bean : 调用 BeanDefinitionRegistry.registryBeanDefinition手工注册进来
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
// 通过bean名称,判断bean是否在容器中
booean definition = registry.containsBeanDefinition("red");
boolean definition1 = registry.containsBeanDefinition("blue");
if (definition && definition1) {
// 指定bean定义信息 : (Bean的类型,Bean...)
RootBeanDefinition bean = new RootBeanDefinition(RainBow.class);
// 注册一个Bean,指定Bean名
registry.registryBeanDefinition("rainBow", bean);
}
}
}

4 : 例子 :
// 创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
// 返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
return new Color();
}

public Class<?> getObjectType() {
return Color.class;
}

//是单例?
//true : 这个bean是单例,在容器中保存一份
//false : 多实例,每次获取都会创建一个新的bean
@Override
public boolean isSingleton() {
return false
}
}

@Bean
public ColorFactoryBean getBean() {
return new ColorFactoryBean();
}

public void test() {
//工厂Bean获取的是调用getObject创建的对象;实际上获取的是Color对象
Object bean2 = applicatinContext.getBean("colorFactoryBean");
//这个是获取的ColorFactoryBean对象,因为在FactoryBean接口中定义了一个字符串,表示以&开头的就是获取实现FactoryBean接口的对象
Object bean3 = applicatinContext.getBean("&colorFactoryBean");
}
Bean的生命周期
bean创建 -- 初始化 -- 销毁的过程
容器管理bean的生命周期 :
我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁的方法
构造(对象创建)
单实例 : 在容器启动的时候创建对象
多实例 : 在每次获取的时候创建对象

BeanPostProcessor.postProcessBeforeInitialization
初始化 :
对象创建完成,并赋值好,调用初始化方法...
BeanPostProcessor.postProcessInitialization

销毁 :
单实例 : 容器关闭的时候
多实例 : 容器不会管理者bean,容器不会调用销毁方法.

遍历得到容器中所有的BeanPostProcessor : 挨个执行beforeInitialization,一旦返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessBeforeInitialization

BeanPostProcessor的原理
populateBean(beanName, mdb, instanceWrapper) : 给bean进行属性赋值
initializeBean
{
appliyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
}

1) : 指定初始化和销毁方法:
通过@Bean指定init-method和destory-method;
2) : 通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑)
3) : 可以使用JSR250;
@PostConstruct : 在bean创建完成并且属性赋值完成;来执行初始化方法(在对象创建并赋值之后调用)
@PreDestroy : 在容器销毁bean之前通知我们进行清理工作.

例如 :
public class Dog{
public Dog() {
System.out.println("");
}

//对象创建并赋值之后调用
@PostConstruct
public void init() {
System.out.println("11");
}

//容器移除对象之前
@PreDestroy
public void detory(){
}
}
4) : BeanPostProcessor[interface] : bean后置处理器;
在bean初始化前后进行一些处理工作;
postProcessBeforeInitialization : 在初始化之前工作
postProcessInitialization : 在初始化之后工作

Spring底层对BeanPostProcessor的使用 :
bean赋值,注入其他组件,@Autowired,生命周期注解功能。@Async, xxx BeanPostProcessor;

@Value : 给属性赋值。
1. 基本数值 例如 : @Value("111")
2. 可以写SpEL. 例如 : @Value("#{20-2}")
3. 可以写${},取出配置文件中的值(在运行环境变量里面的值) 例如 : @Value("${name}")
@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值。
例如 :
AnnotationConfigApplicationContext applicatinContext = new AnnontationConfigApplicationContext();
pringBeans(applicationContext);
Person person = (Person)applicationContext.getBean("person");
ConfigurableEnvironment environment = applicatinContext.getEnvironment();
// 这是根路径下的.properties配置文件中的k/v值
Sting property = environment.getProperty("person.nickName);
applicatinContext.close();

自动装配 :
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值;
1) . 默认优先按照类型去容器中找对应的组件 : applicationContext.getBean(BookDao.class);找到就赋值
2) . 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
3) . @Qualifier("bookDao") : 使用@Qualifier指定需要装配的组件的id,而不是使用属性名。
4) . 自动装配默认一定要将属性赋值好,没有就会报错。(可以通过更改属性值.例如 : @Autowired(required=false);这样就在没有这个组件时,不会进行自动装配)
5) . @Primary : 让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字。
applicatinContext.getBean("bookDao");
BookService{
@Autowired
BookDao bookDao
}
(2):Spring还支持使用@Resource(JSR250)和@Inject(JSR330)【Java规范的注解】
@Resource
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能没有支持 @Autowired(reqiured = false);
@Inject
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
@Autowired : Spring定义的; @Resouce和@Inject都是java规范。
Spring的@Autowired的底层使用AutowiredAnnotationBeanPostProcessor : 解析完成自动装配功能。
(3):@Autowired : 构造器,参数,方法,属性
@Componetnt : 默认加载ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
1): 标注在方法位置 : @Bean + 方法参数;参数从容器中获取;默认不写@Autowired效果是一样的,都能自动装配
2): 标注在构造器上 : 如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件换是可以自动从容中获取.
3):标注在参数位置
@Bean标注的方法创建对象的时候,方法参数的值从容器中获取。
(4) : 自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware
把Spring底层一些组件注入到自定义的Bean中;
xxxAware: 功能使用xxxProcessor;
ApplicationContextAware ==> ApplicationContextAwareProcessor;
@Profile : 指定组件在哪个环境的情况下才能被注册到容器中。
1) : 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境。
2) : 写在配置上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效。

激活方式 :
(1) : 使用命令行动态参数 : 在虚拟机参数位置加载 -Dspring.profiles.active=test
(2) :代码的方式激活某种环境。
(3) : 没有标注环境标识的bean在任何环境下都是加载的。
例如 :
AnnotationConfigApplicationContext applicatinContext = new AnnontationConfigApplicationContext();
//1。创建一个applicationContext
//2. 设置需要激活的环境
applicatinContext.getEnvironment().setActiveProfiles("dev");
//3.注册主配置类
applicatinContext.registry(MainConfigOrProfile.class);
//4.启动刷新容器
applicatinContext.refresh();

最全的Spring注解详解的更多相关文章

  1. Spring注解详解

    概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...

  2. 【转】Spring注解详解

    http://blog.csdn.net/xyh820/article/details/7303330/ 概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类 ...

  3. Spring注解详解@Repository、@Component、@Service 和 @Constroller

    概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...

  4. Spring @注解详解(转)

    1.@controller 控制器(注入服务) 2.@service 服务(注入dao) 3.@repository dao(实现dao访问) 4.@component (把普通pojo实例化到spr ...

  5. Spring注解详解(转)

    概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...

  6. Spring注解详解(转)

    概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...

  7. [Spring学习笔记 3 ] spring 注解详解,完全注解,常用注解

    .xml使用注解 xml 用来定义bean的信息,注解用来配置依赖信息 ) 在配置文件中配置bean )在javaBean中用注解来指定依赖注入 )在配置文件中开启注解扫描 @Resource标签 j ...

  8. Spring IoC 公共注解详解

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 什么是公共注解?公共注解就是常见的Java ...

  9. Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

随机推荐

  1. 【LeetCode】039. Combination Sum

    题目: Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all uniq ...

  2. Godot-3D教程-01.介绍3D

    创建一个3D游戏将是个挑战,额外增加的Z坐标将使许多用于2D游戏的通用技术不再有用.为了帮助变换(transition),值得一提的是Godot将使用十分相似的API用于2D和3D. 目前许多节点是公 ...

  3. 洛谷【P3437】[POI2006]TET-Tetris 3D

    浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html 浅谈标记永久化:https://www.cnblogs.com/AKMer/p/1013 ...

  4. Jenkins持续集成环境搭建

    1部署Jenkins Jenkins部署很简单,只需建立一个新应用,将Jenkins的war包部署进去,再分配好权限就可以了. 1.1创建应用 建立一个新Nginx应用:jenkins.com 1.2 ...

  5. ssh免密脚本

    #!/bin/sh if [ "$1"x = ""x ]; then echo "usage:/opt/bin/auto-ssh.sh user se ...

  6. DTP模型之一:(XA协议之三)MySQL数据库分布式事务XA优缺点与改进方案

    1 MySQL 外部XA分析 1.1 作用分析 MySQL数据库外部XA可以用在分布式数据库代理层,实现对MySQL数据库的分布式事务支持,例如开源的代理工具:ameoba[4],网易的DDB,淘宝的 ...

  7. Ternary Calculation

    Ternary Calculation Time Limit : /2000ms (Java/Other) Memory Limit : /65536K (Java/Other) Total Subm ...

  8. openstack实现nova-api的HA

    1       实验环境 Openstack juno版本,一个controller(计算节点也在这个物理节点上)和一个网络节点network 使用haproxy作为代理软件 使用pacemaker作 ...

  9. thinkpad取消fn键功能

    转自:https://bbs.thinkpad.com/thread-1834235-1-1.html 1就是一直觉得fn建自动开启很烦人,于是百度后得到 我们可以 控制面板 -- 键盘--think ...

  10. va_list函数学习

    当你的函数的参数个数不确定时,就可以使用上述宏进行动态处理,这无疑为你的程序增加了灵活性. va_list的使用方法: a)  首先在函数中定义一个具有va_list型的变量,这个变量是指向参数的指针 ...