02、组件注册-@Configuration&@Bean给容器中注册组件
03、组件注册-@ComponentScan-自动扫描组件&指定扫描规则
04、组件注册-自定义TypeFilter指定过滤规则
@Configuration //告诉Spring这是一个配置类 @ComponentScans( value = { @ComponentScan(value = "com.learn", 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) } ) //@ComponentScan value:指定要扫描的包 //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件 //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件 //FilterType.ANNOTATION:按照注解 //FilterType.ASSIGNABLE_TYPE:按照给定的类型; //FilterType.ASPECTJ:使用ASPECTJ表达式 //FilterType.REGEX:使用正则指定 //FilterType.CUSTOM:使用自定义规则 public class MainConfig { //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id @Bean("person") public Person person01() { return new Person("lisi", 20); } }
05、组件注册-@Scope-设置组件作用域
06、组件注册-@Lazy-bean懒加载
07、组件注册-@Conditional-按照条件注册bean
08、组件注册-@Import-给容器中快速导入一个组件
给容器中注入注解组件:
1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
2)、@Bean[导入的第三方包里面的组件]
3)、@Import [快速给容器中导入一个组件]
09、组件注册-@Import-使用ImportSelector
10、组件注册-@Import-使用ImportBeanDefinitionRegistrar
11、组件注册-使用FactoryBean注册组件
@Conditional({WindowsCondition.class}) @Configuration @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) //@Import导入组件,id默认是组件的全类名 public class MainConfig2 { //默认是单实例的 /** * ConfigurableBeanFactory#SCOPE_PROTOTYPE * * @return * @Scope:调整作用域 prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。 * 每次获取的时候才会调用方法创建对象; * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。 * 以后每次获取就是直接从容器(map.get())中拿, * request:同一次请求创建一个实例 * session:同一个session创建一个实例 * <p> * 懒加载: * 单实例bean:默认在容器启动的时候创建对象; * 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化; * @see ConfigurableBeanFactory#SCOPE_SINGLETON * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION sesssion */ // @Scope("prototype") @Lazy @Bean("person") public Person person() { System.out.println("给容器中添加Person...."); return new Person("张三", 25); } /** * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean * <p> * 如果系统是windows,给容器中注册("bill") * 如果是linux系统,给容器中注册("linus") */ @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)、包扫描+组件标注注解(@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 */ @Bean public ColorFactoryBean colorFactoryBean() { return new ColorFactoryBean(); } }
12、生命周期-@Bean指定初始化和销毁方法
13、生命周期-InitializingBean和DisposableBean
14、生命周期-@PostConstruct&@PreDestroy
15、生命周期-BeanPostProcessor-后置处理器
16、生命周期-BeanPostProcessor原理
17、生命周期-BeanPostProcessor在Spring底层的使用
/** * bean的生命周期: * bean创建---初始化----销毁的过程 * 容器管理bean的生命周期; * 我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法 * * 构造(对象创建) * 单实例:在容器启动的时候创建对象 * 多实例:在每次获取的时候创建对象 * * BeanPostProcessor.postProcessBeforeInitialization * 初始化: * 对象创建完成,并赋值好,调用初始化方法。。。 * BeanPostProcessor.postProcessAfterInitialization * 销毁: * 单实例:容器关闭的时候 * 多实例:容器不会管理这个bean;容器不会调用销毁方法; * * * 遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization, * 一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization * * BeanPostProcessor原理 * populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值 * initializeBean * { * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); * invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化 * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); *} * * * * 1)、指定初始化和销毁方法; * 通过@Bean指定init-method和destroy-method; * 2)、通过让Bean实现InitializingBean(定义初始化逻辑), * DisposableBean(定义销毁逻辑); * 3)、可以使用JSR250; * @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法 * @PreDestroy:在容器销毁bean之前通知我们进行清理工作 * 4)、BeanPostProcessor【interface】:bean的后置处理器; * 在bean初始化前后进行一些处理工作; * postProcessBeforeInitialization:在初始化之前工作 * postProcessAfterInitialization:在初始化之后工作 * * Spring底层对 BeanPostProcessor 的使用; * bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor; * * */ @ComponentScan("com.learn.bean") @Configuration public class MainConfigOfLifeCycle { //@Scope("prototype") @Bean(initMethod="init",destroyMethod="detory") public Car car(){ return new Car(); } }
18、属性赋值-@Value赋值
19、属性赋值-@PropertySource加载外部配置文件
/** * Profile: * Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能; * * 开发环境、测试环境、生产环境; * 数据源:(/A)(/B)(/C); * * * @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件 * * 1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境 * 2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效 * 3)、没有标注环境标识的bean在,任何环境下都是加载的; */ @PropertySource(value={"classpath:/dbconfig.properties"}) @Configuration public class MainConfigOfProfile implements EmbeddedValueResolverAware{ @Value("${db.user}") private String user; private StringValueResolver valueResolver; private String driverClass; @Profile("test") @Bean public Yellow yellow(){ return new Yellow(); } @Profile("test") @Bean("testDataSource") public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(pwd); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); dataSource.setDriverClass(driverClass); return dataSource; } @Profile("dev") @Bean("devDataSource") public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(pwd); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud"); dataSource.setDriverClass(driverClass); return dataSource; } @Profile("prod") @Bean("prodDataSource") public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser(user); dataSource.setPassword(pwd); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515"); dataSource.setDriverClass(driverClass); return dataSource; } @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { this.valueResolver = resolver; driverClass = valueResolver.resolveStringValue("${db.driverClass}"); } }
20、自动装配-@Autowired&@Qualifier&@Primary
21、自动装配-@Resource&@Inject
22、自动装配-方法、构造器位置的自动装配
23、自动装配-Aware注入Spring底层组件&原理
/** * 自动装配; * Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值; * * 1)、@Autowired:自动注入: * 1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值 * 2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找 * applicationContext.getBean("bookDao") * 3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名 * 4)、自动装配默认一定要将属性赋值好,没有就会报错; * 可以使用@Autowired(required=false); * 5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean; * 也可以继续使用@Qualifier指定需要装配的bean的名字 * 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定义的; @Resource、@Inject都是java规范 * * AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能; * * 3)、 @Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值 * 1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配 * 2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取 * 3)、放在参数位置: * * 4)、自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx); * 自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware; * 把Spring底层一些组件注入到自定义的Bean中; * xxxAware:功能使用xxxProcessor; * ApplicationContextAware==》ApplicationContextAwareProcessor; * * * */ @Configuration @ComponentScan({"com.learn.service","com.learn.dao", "com.learn.controller","com.learn.bean"}) public class MainConifgOfAutowired { @Primary @Bean("bookDao2") public BookDao bookDao(){ BookDao bookDao = new BookDao(); bookDao.setLable("2"); return bookDao; } /** * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取 * @param car * @return */ @Bean public Color color(Car car){ Color color = new Color(); color.setCar(car); return color; } }
24、自动装配-@Profile环境搭建.avi
25、自动装配-@Profile根据环境注册bean
(1)使用命令行动态参数:见第19配置好不同数据源,在虚拟机位置添加:-Dspring.profiles.active=test
(2) 代码的方式激活某种环境
@Test public void test01(){ /* * AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class); * 源码: * public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { * this(); * register(annotatedClasses); * refresh(); * } * 改造成无参构造: * register(annotatedClasses)与refresh()仍然需要执行 * */ // 1、创建一个AnnotationConfigApplicationContext AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 2、设置激活的环境 ;源码(可以同时激活多种环境):public void setActiveProfiles(String... profiles) context.getEnvironment().setActiveProfiles("dev"); // 3、设置主配置类 context.register(MainConfigOfAutowired.class); // 4、刷新容器 context.refresh(); }
26、IOC-小结