一、Spring容器
1.1、使用spring注解的优势
①:采用纯java代码,不再需要配置繁杂的xml文件
②:在配置中也可享受面向对象带来的好处
③:类型安全对重构可以提供良好的支持
④:减少复杂配置文件的同时亦能享受到springIoC容器提供的功能
1.2、@Configuration注解
定义一个MainConfig,用@Configuration注解,那MainConfig相当于xml里的beans,里面用@Bean注解的和xml里定义的bean等价,用<context:component-scanbase-package=”XXX”/>扫描该类,最终我们可以在程序里用@AutoWired或@Resource注解取得用@Bean注解的bean,和用xml先配置bean然后在程序里自动注入一样。目的是减少xml里配置。
//配置类==配置文件
@Configuration//告诉Spring这是一个配置类
public class MainConfig {
// 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean
public Person person(){
return new Person ( "lisi","20" );
}
}
@ComponentScan(value = "com.yjq",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes ={Controller.class, Service.class}
)})
//@ComponentScan value:指定要扫描的包
// excludeFilters =Filter[]:指定扫描的时候按照什么规则排除的包
// includeFilters = Filter[]:指定扫描的时候只需要包含哪些组件
@Scope("prototype")
// prototype:多实例的,IOC容器启动并不会去调用方法创建对象放在容器中。
// 每次获取的时候才会调用方法创建对象
// Singleton:单实例的默认值,IOC容器启动会调用方法创建对象放到IOC容器中,以后每次获取就是直接从容器中拿
@Lazy//懒加载
// 懒加载:
// 单实例bean,默认在容器启动的时候创建对象;
// 赖加载:容器启动不创建对象,第一次使用Bean创建对象,并初始化
1.3、组件注册
Spring组件有十几种,但是核心的只有三个,分别是:Context、Core、Bean。
这三个组件的关系是什么呢?
--Context:容器;--Core:关系;--Bean:实物
IOC容器:Ioc—Inversion of Control,即“控制反转”,就是具有依赖注入功能的容器,是可以创建对象的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
即在springIOC运行容器中(Context)中,通过Core建立维护各个bean之间的关系。我们所说的组件注册就是:把bean对象交给IOC容器管理。
1.4、组件注册的几种方式
1.4.1、@Bean给容器注册组件[导入的第三方包里面的组件]
@Configuration
public class MyConfig {
@Scope("prototype")
@Lazy
@Bean(value = "pp",name = "pp")
public Person person(){
return new Person("jiajia",26);
}
代码中用到的注解说明:
@Configuration:配置类 相当于配置文件,告诉spring这是一个配置类
@Scope:调整作用域 ,可取值【singleton,prototype,request,session】
-singleton:单实例(默认值):ioc容器启动会调用方法创建对象放到ioc容器中, 以后每次获取就是直接从容器中拿;
-prototype:多实例,ioc容器启动并不会去调用方法创建对象放在容器中,每次获取的时候才会调用方法创建对象;
-request:同一次请求创建一个实例
-session:同一个session创建一个实例
@Lazy :是只针对单实例。
单实例Bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化;
@Bean:如果不设置value的话默认是采用方法名 person为组件名
1.4.2、@ComponentScan 组件扫描注解:包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
@ComponentScan(value = "com.athome", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class,Controller.class}),
@ComponentScan.Filter(type = FilterType.REGEX,pattern = "com\\.athome\\.core\\.message\\..*")
})
@Configuration
public class MyConfig {
@Bean
public Person person(){
return new Person("niHao",26);
}
}
该注解几个重要的属性:
1)basePackages/value 表示扫描的路径是一个String[]
2)includeFilters 包含过滤器Filter[] ,指定扫描符合条件的组件
3)excludeFilters 排除过滤器Filter[] ,不扫描不符合条件的组件
4)useDefaultFilters 默认的扫描策略默认为true,如果想要用自定义的策略 该值要设为false和includeFilters一起使用
1.4.3、@Conditional({condition}) 按条件注册bean
在spring4中引入,用到带有@Bean注解的方法上,如果给定的条件计算结果为true,则会创建这个bean,否则这个bean就会被忽略。
1.4.4、@import注解导入组件
@Import主要是用来引用第三方组件,当然也可以导入自定义的组件。
1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
2)、ImportSelector:返回需要导入的组件的全类名数组;
3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
1.4.5、使用Spring提供的 FactoryBean(工厂Bean)
1)、默认获取到的是工厂bean调用getObject创建的对象
2)、要获取工厂Bean本身,我们需要给id前面加一个&
二、Bean的生命周期
2.1、什么是bean
Spring Bean是被实例化的,组装的及被Spring容器管理的java对象。
Spring容器会自动完成@Bean对象的实例化。
创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。
2.2、Bean生命周期的几种方式
* bean的生命周期:
* bean的创建---初始化---销毁的过程
* 容器管理bean的生命周期
* 我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
*
* 构造(对象创建)
* 单实例:在容器启动的时候创建对象
* 多实例:在每次获取的时候创建对象
* 初始化:
* 对象创建完成,并赋值后,调用初始化方法。。。
* 销毁:
* 单实例:容器关闭的时候;
* 多实例:容器不会管理这个bean,容器不会调用销毁方法
.2.2.1、通过@Bean注解指定初始化和销毁方法
@Bean(initMethod = "init",destroyMethod = "destroy")
@Configuration
public class MyLifeCycleConfig {
@Scope("prototype")
@Bean(initMethod = "init",destroyMethod = "destroy")
public Dog dog(){
return new Dog();
}
}
applicationContext.close();关闭容器
单实例: 调用close()关闭容器,则会调用销毁方法
多实例: 调用close()关闭容器,则不会调用销毁方法
2.2.2、实现初始化接口InitializingBean 和 销毁接口DisposableBean
通过让Bean实现InitializingBean(定义初始化逻辑); DisposableBean(定义销毁逻辑);
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat(){
System.out.println("cat...构造器...");
}
public void destroy() throws Exception {
System.out.println("cat ....destroy....");
}
public void afterPropertiesSet() throws Exception {
System.out.println("cat ...afterPropertiesSet....");
}
}
2.2.3、 使用JSR250 java中的注解
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
@Component
public class Tiger {
public Tiger(){
System.out.println("tiger...constructor....");
}
@PostConstruct
public void init(){
System.out.println("tiger....@postConstruct...");
}
@PreDestroy
public void destroy(){
System.out.println("tiger....@PreDestroy.....");
}
}
2.2.4、使用接口 BeanPostProcessor :bean的后置处理器;
接口BeanPostProcessor是 在bean初始化前后进行一些处理工作;
--postProcessBeforeInitialization:在初始化之前工作
-- postProcessAfterInitialization:在初始化之后工作
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
return bean;
}
}
三、自动配置
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系复制。
3.1、@Autowired & @Qualifier & @Primary
1):默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋
值。
2):如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean(“bookDao”)
3):@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
4):自动装配默认一定要将属性赋值好,没有就会报错;
5):@Primary:让Spring进行自动装配的时候,默认使用首选的bean;也可以继续使用@Qualifier指定需要装配的bean的名字,如果这两个同时使用,@Qualifier的优 先级高于@Primary
3.2、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
1):可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
2):需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
3.4、Aware注入Spring底层组件&原理
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx)
原理:Bean在创建对象的时候后置处理器会查看是否实现了XXXAware接口,如果实现了,会调用对应的方法将 组件注入到方法中
3.5、@Profile 根据环境注册bean
spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能。
@Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
3)、没有标注环境标识的bean在,任何环境下都是加载的;