本文共 11574 字,大约阅读时间需要 38 分钟。
目录
作用:告诉Spring这是一个配置类
@Configuration //告诉Spring这是一个配置类public class MainConfig {}
作用:给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id,也可以通过value属性设置id
@Configuration //告诉Spring这是一个配置类public class MainConfig { //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id @Bean("person") public Person person01(){ return new Person("lisi", 20); }}
作用:开启组件扫描
参数:
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; }}
作用:调整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); }
作用:懒加载
说明:
单实例bean会默认在容器启动的时候创建对象,懒加载即在容器启动时不创建对象。第一次使用(获取)Bean创建对象,并初始化;
@Lazy @Bean("person") public Person person(){ System.out.println("给容器中添加Person...."); return new Person("张三", 25); }
作用:按照一定的条件进行判断,满足条件给容器中注册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); }
作用:快速给容器中导入一个组件
方式:
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 {}
作用:使用Spring提供的 FactoryBean(工厂Bean)
特点:
1)、默认获取到的是工厂bean调用getObject创建的对象
2)、要获取工厂Bean本身,我们需要给id前面加一个& (&colorFactoryBean)
Object bean4 = applicationContext.getBean("&colorFactoryBean");
实现FactoryBean接口
//创建一个Spring定义的FactoryBeanpublic class ColorFactoryBean implements FactoryBean{ //返回一个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指定init-method和destroy-method
Car.class
@Componentpublic 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(); }
说明:通过让Bean实现InitializingBean(定义初始化逻辑);DisposableBean(定义销毁逻辑)。
@Componentpublic 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..."); }}
说明:
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
@Componentpublic 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..."); }}
说明:在bean初始化前后进行一些处理工作。
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作
/** * 后置处理器:初始化前后进行处理工作 * 将后置处理器加入到容器中 * @author lfy */@Componentpublic 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读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值
person.properties配置文件
person.nickName=小张三
配置类中引入配置文件
@PropertySource(value={"classpath:/person.properties"})@Configurationpublic class MainConfigOfPropertyValues { @Bean public Person person(){ return new Person(); }}
可以赋值的类型:
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 + "]"; }}
特点:
(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; } }
@Repositorypublic 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 + "]"; }}
@Servicepublic class BookService { @Autowired(required=false) private BookDao bookDao; public void print(){ System.out.println(bookDao); } @Override public String toString() { return "BookService [bookDao=" + bookDao + "]"; }}
作用:使用@Qualifier指定需要装配的组件的id,而不是使用属性名
示例:如下代码,自动装配的是bookDao而不是bookDao2
@Servicepublic class BookService { @Qualifier("bookDao") @Autowired() private BookDao bookDao2; public void print(){ System.out.println(bookDao); } @Override public String toString() { return "BookService [bookDao=" + bookDao + "]"; } }
作用:让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; }}
未完待续~~~~
转载地址:http://ffirn.baihongyu.com/