目录
实现InitializingBean和DisposableBean接口
一、组件注册
@Configuration
作用:告诉Spring这是一个配置类
@Configuration //告诉Spring这是一个配置类
public class MainConfig {}
@Bean
作用:给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id,也可以通过value属性设置id
@Configuration //告诉Spring这是一个配置类
public class MainConfig {
//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
}
}
@ComponentScan
作用:开启组件扫描
参数:
value:指定要扫描的包
excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
FilterType.ANNOTATION:按照注解类型过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型过滤
FilterType.ASPECTJ:使用ASPECTJ表达式过滤
FilterType.REGEX:使用正则表达式过滤
FilterType.CUSTOM:使用自定义规则过滤
@Configuration //告诉Spring这是一个配置类
@ComponentScans(
value = {
@ComponentScan(value="com.atguigu",includeFilters = {
/* @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),*/
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
},useDefaultFilters = false)
}
)
public class MainConfig {
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
}
}
自定义规则
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader:读取到的当前正在扫描的类的信息
* metadataReaderFactory:可以获取到其他任何类信息的
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// TODO Auto-generated method stub
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->"+className);
if(className.contains("er")){
return true;
}
return false;
}
}
@Scope
作用:调整JavaBean的作用域
参数:
prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。(每次获取的时候才会调用方法创建对象)
singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。(以后每次获取就是直接从容器map.get()中拿)
request:同一次请求创建一个实例
session:同一个session创建一个实例
@Scope("prototype")
@Bean("person")
public Person person(){
System.out.println("给容器中添加Person....");
return new Person("张三", 25);
}
@Lazy
作用:懒加载
说明:
单实例bean会默认在容器启动的时候创建对象,懒加载即在容器启动时不创建对象。第一次使用(获取)Bean创建对象,并初始化;
@Lazy
@Bean("person")
public Person person(){
System.out.println("给容器中添加Person....");
return new Person("张三", 25);
}
@Conditional
作用:按照一定的条件进行判断,满足条件给容器中注册bean
示例:
(1)如果系统是windows,给容器中注册("bill")
(2)如果是linux系统,给容器中注册("linus")
判定条件(Linux)
//判断是否linux系统
public class LinuxCondition implements Condition {
/**
* ConditionContext:判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata:注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO是否linux系统
//1、能获取到ioc使用的beanfactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2、获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3、获取当前环境信息
Environment environment = context.getEnvironment();
//4、获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean definition = registry.containsBeanDefinition("person");
if(property.contains("linux")){
return true;
}
return false;
}
}
判断条件(Windows)
//判断是否windows系统
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("Windows")){
return true;
}
return false;
}
}
注解使用示例
@Conditional(WindowsCondition.class)
@Bean("bill")
public Person person01(){
return new Person("Bill Gates",62);
}
@Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02(){
return new Person("linus", 48);
}
@import
作用:快速给容器中导入一个组件
方式:
1)@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
2)ImportSelector:返回需要导入的组件的全类名数组;
3)ImportBeanDefinitionRegistrar:手动注册bean到容器中
实现ImportSelector接口
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
//返回值,就是到导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//方法不要返回null值
return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
}
}
实现ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类;
* 把所有需要添加到容器中的bean;调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
if(definition && definition2){
//指定Bean定义信息;(Bean的类型,Bean。。。)
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
}
注解使用示例
//类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
@Conditional({WindowsCondition.class})
@Configuration
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {}
FactoryBean
作用:使用Spring提供的 FactoryBean(工厂Bean)
特点:
1)、默认获取到的是工厂bean调用getObject创建的对象
2)、要获取工厂Bean本身,我们需要给id前面加一个& (&colorFactoryBean)
Object bean4 = applicationContext.getBean("&colorFactoryBean");
实现FactoryBean接口
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
// TODO Auto-generated method stub
System.out.println("ColorFactoryBean...getObject...");
return new Color();
}
@Override
public Class<?> getObjectType() {
// TODO Auto-generated method stub
return Color.class;
}
//是单例?
//true:这个bean是单实例,在容器中保存一份
//false:多实例,每次获取都会创建一个新的bean;
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}
}
二、生命周期
@Bean指定初始化和销毁方法
说明:通过@Bean指定init-method和destroy-method
Car.class
@Component
public class Car {
public Car(){
System.out.println("car constructor...");
}
public void init(){
System.out.println("car ... init...");
}
public void detory(){
System.out.println("car ... detory...");
}
}
@Bean(initMethod="init",destroyMethod="detory")
public Car car(){
return new Car();
}
实现InitializingBean和DisposableBean接口
说明:通过让Bean实现InitializingBean(定义初始化逻辑);DisposableBean(定义销毁逻辑)。
@Component
public class Cat implements InitializingBean,DisposableBean {
public Cat(){
System.out.println("cat constructor...");
}
@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub
System.out.println("cat...destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println("cat...afterPropertiesSet...");
}
}
JSR250
说明:
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
@Component
public class Dog implements ApplicationContextAware {
public Dog(){
System.out.println("dog constructor...");
}
//对象创建并赋值之后调用
@PostConstruct
public void init(){
System.out.println("Dog....@PostConstruct...");
}
//容器移除对象之前
@PreDestroy
public void detory(){
System.out.println("Dog....@PreDestroy...");
}
}
BeanPostProcessor(bean的后置处理器)
说明:在bean初始化前后进行一些处理工作。
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作
/**
* 后置处理器:初始化前后进行处理工作
* 将后置处理器加入到容器中
* @author lfy
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
return bean;
}
}
总结
1.关于初始化和销毁
(1)初始化:对象创建完成,并赋值好,调用初始化方法。。。
(2)销毁:单实例:容器关闭的时候;多实例:容器不会管理这个bean;容器不会调用销毁方法;
2.BeanPostProcessor原理
第一步
(1)populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
第二步
(2)initializeBean(调用初始化方法)
(2.1)applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);在初始化之前执行
(2.2)invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
(2.3)applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);在初始化之后执行
3.Spring底层对 BeanPostProcessor 的使用
(1)bean赋值,注入其他组件
(2)@Autowired,生命周期注解功能
(3)@Async,xxx BeanPostProcessor;
三、属性赋值
@PropertySource
说明:使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值
person.properties配置文件
person.nickName=小张三
配置类中引入配置文件
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
@Bean
public Person person(){
return new Person();
}
}
@Value
可以赋值的类型:
1、基本数值
2、可以写SpEL; #{}
3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
public class Person {
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${person.nickName}")
private String nickName;
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
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;
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", nickName=" + nickName + "]";
}
}
四、自动装配
@Autowired
特点:
(1)默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
(2)如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean("bookDao")
(3)可以使用@Autowired(required=false),允许找不到对应的JavaBean对象。
示例:如下有两个BookDao的实现类,自动装配默认会去绑定属性名称相同的实现类,即bookDao,而不是bookDao2
@Configuration
@ComponentScan({"com.atguigu.service","com.atguigu.dao",
"com.atguigu.controller","com.atguigu.bean"})
public class MainConifgOfAutowired {
@Bean("bookDao2")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
@Repository
public class BookDao {
private String lable = "1";
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
@Override
public String toString() {
return "BookDao [lable=" + lable + "]";
}
}
@Service
public class BookService {
@Autowired(required=false)
private BookDao bookDao;
public void print(){
System.out.println(bookDao);
}
@Override
public String toString() {
return "BookService [bookDao=" + bookDao + "]";
}
}
@Qualifier
作用:使用@Qualifier指定需要装配的组件的id,而不是使用属性名
示例:如下代码,自动装配的是bookDao而不是bookDao2
@Service
public class BookService {
@Qualifier("bookDao")
@Autowired()
private BookDao bookDao2;
public void print(){
System.out.println(bookDao);
}
@Override
public String toString() {
return "BookService [bookDao=" + bookDao + "]";
}
}
@Primary
作用:让Spring进行自动装配的时候,默认使用首选的bean;也可以继续使用@Qualifier指定需要装配的bean的名字
@Configuration
@ComponentScan({"com.atguigu.service","com.atguigu.dao",
"com.atguigu.controller","com.atguigu.bean"})
public class MainConifgOfAutowired {
@Primary
@Bean("bookDao2")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
未完待续~~~~