资料来源:https://www.bilibili.com/video/BV1gW411W7wy/?spm_id_from=333.788.recommend_more_video.10

一、组件注册

1、@Configuration

通过注解注入JavaBean

  1. // 这个配置类也是一个组件
  2. @Configuration // 告诉Spring这是一个配置类
  3. public class MainConfig {
  4. // @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
  5. @Bean(name = "person01") // 指定名称,不然就默认为方法名person
  6. public Person person() {
  7. return new Person("liayun", 20);
  8. }
  9. }
  1. 通过在MainConfig类上加上@Configuration注解,并在方法上加上@Bean注解,就能够将方法中创建的JavaBean注入到SpringIOC容器中。
  1. // ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
  2. // Person bean = (Person) applicationContext.getBean("person");
  3. // System.out.println(bean);
  4. ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
  5. Person bean = applicationContext.getBean(Person.class);
  6. System.out.println(bean); // Person [name=lisi, age=20, nickName=null]
  7. // 获取Person这个类型的组件在IOC容器中的名字
  8. String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
  9. for (String name : namesForType) {
  10. System.out.println(name); // person01,若没有指定名称,就默认为方法名person
  11. }

2、@ComponentScan

  1. // 配置类==配置文件
  2. @Configuration // 告诉Spring这是一个配置类
  3. @ComponentScans(value = {
  4. @ComponentScan(value="com.atguigu",includeFilters = {
  5. /* @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
  6. @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),*/
  7. @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
  8. }, useDefaultFilters = false)})
  9. //@ComponentScan value:指定要扫描的包
  10. //@ComponentScans 指定多个扫描规则
  11. //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
  12. //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
  13. //FilterType.ANNOTATION:按照注解。如Controller.class表示只扫描@Controller注解
  14. //FilterType.ASSIGNABLE_TYPE:按照给定的类型;
  15. //FilterType.ASPECTJ:使用ASPECTJ表达式
  16. //FilterType.REGEX:使用正则指定
  17. //FilterType.CUSTOM:使用自定义规则
  18. public class MainConfig {
  19. // 给容器中注册一个Bean; 类型为返回值的类型,id默认是用方法名作为id
  20. @Bean(name = "person01") // 指定名称,不然就默认为方法名person
  21. public Person person(){
  22. return new Person("lisi", 20);
  23. }
  24. }
  1. // 自定义规则
  2. public class MyTypeFilter implements TypeFilter {
  3. /**
  4. * metadataReader:读取到的当前正在扫描的类的信息
  5. * metadataReaderFactory: 可以获取到其他任何类信息的
  6. */
  7. @Override
  8. public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
  9. // TODO Auto-generated method stub
  10. //获取当前类注解的信息
  11. AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
  12. //获取当前正在扫描的类的类信息
  13. ClassMetadata classMetadata = metadataReader.getClassMetadata();
  14. //获取当前类资源(类的路径)
  15. Resource resource = metadataReader.getResource();
  16. String className = classMetadata.getClassName();
  17. System.out.println("--->" +className);
  18. if(className.contains("er")){
  19. return true; // 匹配成功,给容器中注册bean
  20. }
  21. return false; // 匹配失败
  22. }
  23. }

3、@Scope

  1. //默认是单实例的
  2. /**
  3. * ConfigurableBeanFactory#SCOPE_PROTOTYPE
  4. * @see ConfigurableBeanFactory#SCOPE_SINGLETON
  5. * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request
  6. * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION sesssion
  7. * @return\
  8. * @Scope:调整作用域
  9. * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。
  10. * 每次获取的时候才会调用方法创建对象;
  11. * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。
  12. * 以后每次获取就是直接从容器(map.get())中拿,
  13. * request:同一次请求创建一个实例
  14. * session:同一个session创建一个实例
  15. */
  16. @Scope("prototype")
  17. @Bean(name = "person")
  18. public Person person(){
  19. System.out.println("给容器中添加Person....");
  20. return new Person("张三", 25);
  21. }

4、@Lazy

  1. /**
  2. * 懒加载:
  3. * 单实例bean:默认在容器启动的时候创建对象;
  4. * 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
  5. */
  6. @Lazy
  7. @Bean(name = "person")
  8. public Person person(){
  9. System.out.println("给容器中添加Person....");
  10. return new Person("张三", 25);
  11. }

5、@Conditional

  1. // 类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;此时方法上的@Conditional注解会失效
  2. @Conditional({WindowsCondition.class})
  3. @Configuration
  4. public class MainConfig2 {
  5. /**
  6. * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
  7. *
  8. * 如果系统是windows,给容器中注册("bill")
  9. * 如果是linux系统,给容器中注册("linus")
  10. */
  11. // @Conditional({WindowsCondition.class})
  12. @Bean(name = "bill")
  13. public Person person01(){
  14. return new Person("Bill Gates",62);
  15. }
  16. @Conditional(LinuxCondition.class)
  17. @Bean(name = "linus")
  18. public Person person02(){
  19. return new Person("linus", 48);
  20. }
  21. }
  1. // 判断是否linux系统
  2. public class LinuxCondition implements Condition {
  3. /**
  4. * ConditionContext:判断条件能使用的上下文(环境)
  5. * AnnotatedTypeMetadata:注释信息
  6. */
  7. @Override
  8. public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  9. // TODO是否linux系统
  10. //1、能获取到ioc使用的beanfactory
  11. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  12. //2、获取类加载器
  13. ClassLoader classLoader = context.getClassLoader();
  14. //3、获取当前环境信息
  15. Environment environment = context.getEnvironment();
  16. //4、获取到bean定义的注册类
  17. BeanDefinitionRegistry registry = context.getRegistry();
  18. String property = environment.getProperty("os.name");
  19. //可以判断容器中的bean注册情况,也可以给容器中注册bean
  20. boolean definition = registry.containsBeanDefinition("person");
  21. if(property.contains("linux")){
  22. return true;
  23. }
  24. return false;
  25. }
  26. }
  1. // 判断是否windows系统
  2. public class WindowsCondition implements Condition {
  3. @Override
  4. public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  5. // 获取IOC容器环境
  6. Environment environment = context.getEnvironment();
  7. // 动态获取环境变量的值;Windows 10
  8. String property = environment.getProperty("os.name");
  9. if(property.contains("Windows")){
  10. return true;
  11. }
  12. return false;
  13. }
  14. }

6、@Import

  1. @Configuration
  2. @Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
  3. // @Import导入组件,id默认是组件的全类名
  4. public class MainConfig2 {
  5. /**
  6. * 给容器中注册组件;
  7. * 1、包扫描 + 组件标注注解(@Controller/@Service/@Repository/@Component)[针对自己写的类]
  8. * 2、@Bean[导入的第三方包里面的组件]
  9. * 3、@Import[快速给容器中导入一个组件]
  10. * 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
  11. * 2)、ImportSelector:返回需要导入的组件的全类名数组;
  12. * 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
  13. * 4、使用Spring提供的 FactoryBean(工厂Bean);
  14. * 1)、默认获取到的是工厂bean调用getObject创建的对象
  15. * 2)、要获取工厂Bean本身,我们需要给id前面加一个&
  16. * &colorFactoryBean
  17. */
  18. @Bean
  19. public ColorFactoryBean colorFactoryBean(){
  20. return new ColorFactoryBean();
  21. }
  22. }
  1. // 自定义逻辑返回需要导入的组件
  2. public class MyImportSelector implements ImportSelector {
  3. // 返回值,就是到导入到容器中的组件全类名
  4. // AnnotationMetadata:当前标注@Import注解的类的所有注解信息
  5. @Override
  6. public String[] selectImports(AnnotationMetadata importingClassMetadata) {
  7. // TODO Auto-generated method stub
  8. // importingClassMetadata
  9. // 方法不要返回null值
  10. return new String[]{"com.atguigu.bean.Blue", "com.atguigu.bean.Yellow"};
  11. }
  12. }
  1. public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
  2. /**
  3. * AnnotationMetadata:当前类的注解信息
  4. * BeanDefinitionRegistry:BeanDefinition注册类;
  5. * 把所有需要添加到容器中的bean;
  6. * 调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
  7. */
  8. @Override
  9. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  10. boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
  11. boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
  12. if(definition && definition2){
  13. // 指定Bean定义信息;(Bean的类型,Bean。。。)
  14. RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
  15. // 注册一个Bean,指定bean名
  16. registry.registerBeanDefinition("rainBow", beanDefinition);
  17. }
  18. }
  19. }

7、FactoryBean

  1. @Configuration
  2. public class MainConfig2 {
  3. /**
  4. * 给容器中注册组件;
  5. * 1)、包扫描 + 组件标注注解(@Controller/@Service/@Repository/@Component)[针对自己写的类]
  6. * 2)、@Bean[导入的第三方包里面的组件]
  7. * 3)、@Import[快速给容器中导入一个组件]
  8. * 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
  9. * 2)、ImportSelector:返回需要导入的组件的全类名数组;
  10. * 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中
  11. * 4)、使用Spring提供的 FactoryBean(工厂Bean);
  12. * 1)、默认获取到的是工厂bean调用getObject创建的对象
  13. * 2)、要获取工厂Bean本身,我们需要给id前面加一个&
  14. * &colorFactoryBean
  15. */
  16. @Bean
  17. public ColorFactoryBean colorFactoryBean(){
  18. return new ColorFactoryBean();
  19. }
  20. }
  1. // 创建一个Spring定义的FactoryBean
  2. public class ColorFactoryBean implements FactoryBean<Color> {
  3. // 返回一个Color对象,这个对象会添加到容器中
  4. @Override
  5. public Color getObject() throws Exception {
  6. // TODO Auto-generated method stub
  7. System.out.println("ColorFactoryBean...getObject...");
  8. return new Color();
  9. }
  10. @Override
  11. public Class<?> getObjectType() {
  12. // TODO Auto-generated method stub
  13. return Color.class;
  14. }
  15. // 是单例?
  16. // true:这个bean是单实例,在容器中保存一份
  17. // false:多实例,每次获取都会创建一个新的bean;
  18. @Override
  19. public boolean isSingleton() {
  20. // TODO Auto-generated method stub
  21. return false;
  22. }
  23. }
  1. @Test
  2. public void testFactoryBean(){
  3. printBeans(applicationContext);
  4. Blue bean = applicationContext.getBean(Blue.class);
  5. System.out.println(bean);
  6. //工厂Bean获取的是调用getObject创建的对象:new Color()
  7. Object bean2 = applicationContext.getBean("colorFactoryBean");
  8. Object bean3 = applicationContext.getBean("colorFactoryBean");
  9. System.out.println("bean的类型:"+bean2.getClass());
  10. System.out.println(bean2 == bean3);
  11. // 获取ColorFactoryBean对象
  12. Object bean4 = applicationContext.getBean("&colorFactoryBean");
  13. System.out.println(bean4.getClass());
  14. }
  15. private void printBeans(AnnotationConfigApplicationContext applicationContext){
  16. String[] definitionNames = applicationContext.getBeanDefinitionNames();
  17. for (String name : definitionNames) {
  18. System.out.println(name);
  19. }
  20. }

二、声明周期

1、@Bean指定初始化和销毁方法

  1. /**
  2. * bean的生命周期:
  3. * bean创建---初始化----销毁的过程
  4. * 容器管理bean的生命周期;
  5. * 我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
  6. *
  7. * 构造(对象创建)
  8. * 单实例:在容器启动的时候创建对象
  9. * 多实例:在每次获取的时候创建对象
  10. *
  11. * BeanPostProcessor.postProcessBeforeInitialization
  12. * 初始化:
  13. * 对象创建完成,并赋值好,调用初始化方法。。。
  14. * BeanPostProcessor.postProcessAfterInitialization
  15. * 销毁:
  16. * 单实例:容器关闭的时候
  17. * 多实例:容器不会管理这个bean;容器不会调用销毁方法;
  18. *
  19. * 遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,
  20. * 一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization
  21. *
  22. * BeanPostProcessor原理
  23. * populateBean(beanName, mbd, instanceWrapper); 给bean进行属性赋值
  24. * initializeBean
  25. * {
  26. * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  27. * invokeInitMethods(beanName, wrappedBean, mbd); 执行自定义初始化
  28. * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  29. *}
  30. *
  31. * 1、指定初始化和销毁方法;
  32. * 通过@Bean指定init-method和destroy-method;
  33. * 2、通过让Bean实现InitializingBean:定义初始化逻辑,在创建完成bean且完成赋值后进行操作
  34. * DisposableBean:定义销毁逻辑,在容器关闭的时候进行调用;
  35. * 3、可以使用JSR250;
  36. * @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
  37. * @PreDestroy:在容器销毁bean之前通知我们进行清理工作
  38. * 4、BeanPostProcessor【interface】:bean的后置处理器;
  39. * 在bean初始化前后进行一些处理工作;
  40. * postProcessBeforeInitialization:在任何初始化(如InitializingBean、afterPropertiesSet、initMethod等)之前工作
  41. * postProcessAfterInitialization:在任何初始化之后工作
  42. *
  43. * Spring底层对 BeanPostProcessor 的使用;
  44. * bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor;
  45. *
  46. * @author lfy
  47. *
  48. */
  49. @ComponentScan("com.atguigu.bean")
  50. @Configuration
  51. public class MainConfigOfLifeCycle {
  52. // @Scope("prototype")
  53. // 指定初始化和销毁方法
  54. @Bean(initMethod="init",destroyMethod="detory")
  55. public Car car(){
  56. return new Car();
  57. }
  58. }
  1. @Component
  2. public class Car {
  3. public Car(){
  4. System.out.println("car constructor...");
  5. }
  6. public void init(){ // 初始化方法
  7. System.out.println("car ... init...");
  8. }
  9. public void detory(){ // 销毁方法
  10. System.out.println("car ... detory...");
  11. }
  12. }

2、initializeBean和DisposableBean

  1. @Component
  2. public class Cat implements InitializingBean, DisposableBean {
  3. public Cat(){
  4. System.out.println("cat constructor...");
  5. }
  6. // 销毁方法,在容器关闭的时候进行调用
  7. @Override
  8. public void destroy() throws Exception {
  9. // TODO Auto-generated method stub
  10. System.out.println("cat...destroy...");
  11. }
  12. // 初始化方法,在创建完成bean且完成赋值后进行操作
  13. @Override
  14. public void afterPropertiesSet() throws Exception {
  15. // TODO Auto-generated method stub
  16. System.out.println("cat...afterPropertiesSet...");
  17. }
  18. }

image.png

3、@PostConstruct和@PreDestroy

  1. @Component
  2. public class Dog {
  3. public Dog(){
  4. System.out.println("dog constructor...");
  5. }
  6. // 对象创建并赋值之后调用
  7. @PostConstruct
  8. public void init(){
  9. System.out.println("Dog....@PostConstruct...");
  10. }
  11. // 容器移除对象之前,相当于回调通知
  12. @PreDestroy
  13. public void detory(){
  14. System.out.println("Dog....@PreDestroy...");
  15. }
  16. }

image.png

4、BeanPostProcessor后置处理器

  1. /**
  2. * 后置处理器:初始化前后进行处理工作
  3. * 将后置处理器加入到容器中
  4. */
  5. @Component
  6. public class MyBeanPostProcessor implements BeanPostProcessor {
  7. @Override
  8. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  9. // TODO Auto-generated method stub
  10. System.out.println("postProcessBeforeInitialization..." + beanName + "=>" + bean);
  11. return bean;
  12. }
  13. @Override
  14. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  15. // TODO Auto-generated method stub
  16. System.out.println("postProcessAfterInitialization..." + beanName + "=>" + bean);
  17. return bean;
  18. }
  19. }

image.png

5、BeanPostProcessor原理

6、BeanPostProcessor在Spring底层的使用

三、属性赋值

1、@Values赋值

  1. @Data
  2. public class Person {
  3. // 使用@Value赋值;
  4. // 1、基本数值
  5. // 2、可以写SpEL; #{}
  6. // 3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
  7. // @Value("zhufeng")
  8. private String name;
  9. // @Value("#{20-2}") 即@Value("18")
  10. private Integer age;
  11. // @Value("${person.nickName}")
  12. private String nickName;
  13. }
  1. @Configuration
  2. public class MainConfigOfPropertyValues {
  3. @Bean
  4. public Person person(){
  5. return new Person();
  6. }
  7. }
  1. ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
  2. Person person = (Person) applicationContext.getBean("person");
  3. System.out.println(person);
  4. ConfigurableEnvironment environment = applicationContext.getEnvironment();
  5. String property = environment.getProperty("person.nickName");
  6. System.out.println(property); // 输出:18
  7. applicationContext.close();

2、@PropertySource

  1. // 使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;
  2. // 加载完外部的配置文件以后使用${}取出配置文件的值
  3. @PropertySource(value={"classpath:/person.properties"})
  4. @Configuration
  5. public class MainConfigOfPropertyValues {
  6. @Bean
  7. public Person person(){
  8. return new Person();
  9. }
  10. }
  1. --外部配置文件person.properties
  2. person.nickName=小李四

四、自动装配

1、@Autowired、@Qualifier、@Primary

  1. /**
  2. * 自动装配;
  3. * Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
  4. *
  5. * 1、@Autowired:自动注入:
  6. * 1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
  7. * 2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
  8. * applicationContext.getBean("bookDao")
  9. * 3)、@Qualifier("bookDao"):使用@Qualifier明确指定需要装配的组件的id,而不是使用属性名
  10. * 4)、自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false);
  11. * 5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
  12. * 也可以继续使用@Qualifier指定需要装配的bean的名字
  13. * BookService{
  14. * @Autowired
  15. * BookDao bookDao; //属性名称:bookDao
  16. * }
  17. *
  18. * 2、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
  19. * @Resource:
  20. * 可以和@Autowired一样实现自动装配功能;默认是按照属性名称进行装配的;
  21. * 没有能支持@Primary功能,没有支持@Autowired(reqiured=false);
  22. * @Inject:
  23. * 需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
  24. * @Autowired是Spring定义的; @Resource、@Inject都是java规范
  25. *
  26. * AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能;
  27. *
  28. * 3、@Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
  29. * 1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配
  30. * 2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
  31. * 3)、放在参数位置:
  32. *
  33. * 4、自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
  34. * 自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
  35. * 把Spring底层一些组件注入到自定义的Bean中;
  36. * xxxAware:功能使用xxxProcessor;
  37. * ApplicationContextAware==》ApplicationContextAwareProcessor;
  38. */
  39. @Configuration
  40. @ComponentScan({"com.atguigu.service","com.atguigu.dao",
  41. "com.atguigu.controller","com.atguigu.bean"})
  42. public class MainConifgOfAutowired {
  43. @Primary
  44. @Bean(destroyMethod = "bookDao2")
  45. public BookDao bookDao(){
  46. BookDao bookDao = new BookDao();
  47. bookDao.setLable("2");
  48. return bookDao;
  49. }
  50. /**
  51. * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取
  52. * @param car
  53. * @return
  54. */
  55. @Bean
  56. public Color color(Car car){
  57. Color color = new Color();
  58. color.setCar(car);
  59. return color;
  60. }
  61. }

2、@Resources、@Inject

  1. /**
  2. * 自动装配;
  3. * Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
  4. *
  5. * 1、@Autowired:自动注入:
  6. * 1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
  7. * 2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
  8. * applicationContext.getBean("bookDao")
  9. * 3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
  10. * 4)、自动装配默认一定要将属性赋值好,没有就会报错;
  11. * 可以使用@Autowired(required=false);
  12. * 5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
  13. * 也可以继续使用@Qualifier指定需要装配的bean的名字
  14. * BookService{
  15. * @Autowired
  16. * BookDao bookDao;
  17. * }
  18. *
  19. * 2、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
  20. * @Resource:
  21. * 可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
  22. * 没有能支持@Primary功能没有支持@Autowired(reqiured=false);
  23. * @Inject:
  24. * 需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
  25. * @Autowired:Spring定义的; @Resource、@Inject都是java规范
  26. *
  27. * AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能;
  28. */
  29. @Configuration
  30. @ComponentScan({"com.atguigu.service","com.atguigu.dao",
  31. "com.atguigu.controller","com.atguigu.bean"})
  32. public class MainConifgOfAutowired {
  33. @Primary
  34. @Bean(destroyMethod = "bookDao2")
  35. public BookDao bookDao(){
  36. BookDao bookDao = new BookDao();
  37. bookDao.setLable("2");
  38. return bookDao;
  39. }
  40. /**
  41. * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取
  42. * @param car
  43. * @return
  44. */
  45. @Bean
  46. public Color color(Car car){
  47. Color color = new Color();
  48. color.setCar(car);
  49. return color;
  50. }
  51. }

3、方法、构造器位置的自动装配

  1. /**
  2. * 自动装配;
  3. * Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
  4. *
  5. * 3)、@Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
  6. * 1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取; 默认不写@Autowired效果是一样的;都能自动装配
  7. * 2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
  8. * 3)、放在参数位置:
  9. */
  10. @Configuration
  11. @ComponentScan({"com.atguigu.service","com.atguigu.dao",
  12. "com.atguigu.controller","com.atguigu.bean"})
  13. public class MainConifgOfAutowired {
  14. /**
  15. * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取
  16. * @param car
  17. * @return
  18. */
  19. @Bean
  20. public Color color(@Autowired Car car){ // 默认不写@Autowired,效果一样
  21. Color color = new Color();
  22. color.setCar(car);
  23. return color;
  24. }
  25. }
  1. // 默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
  2. @Component
  3. public class Boss {
  4. private Car car;
  5. // 构造器要用的组件,都是从容器中获取
  6. // 如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
  7. // @Autowired
  8. public Boss(@Autowired Car car){
  9. this.car = car;
  10. System.out.println("Boss...有参构造器");
  11. }
  12. public Car getCar() {
  13. return car;
  14. }
  15. // @Autowired
  16. // 标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值;
  17. // 方法使用的参数,自定义类型的值从ioc容器中获取
  18. public void setCar(Car car) {
  19. this.car = car;
  20. }
  21. }

4、Aware注入Spring底层组件和原理

  1. /**
  2. * 自动装配;
  3. * Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值;
  4. *
  5. * 4)、自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
  6. * 自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
  7. * 把Spring底层一些组件注入到自定义的Bean中;
  8. * xxxAware:功能使用xxxProcessor;
  9. * ApplicationContextAware ==》ApplicationContextAwareProcessor;
  10. */
  11. @Configuration
  12. @ComponentScan({"com.atguigu.service","com.atguigu.dao",
  13. "com.atguigu.controller","com.atguigu.bean"})
  14. public class MainConifgOfAutowired {
  15. }
  1. @Component
  2. public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
  3. private ApplicationContext applicationContext;
  4. @Override
  5. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6. // TODO Auto-generated method stub
  7. System.out.println("传入的ioc:" + applicationContext); // org.springframework.context.annotation.AnnotationConfigApplicationContext@7f560810
  8. this.applicationContext = applicationContext;
  9. }
  10. @Override
  11. public void setBeanName(String name) {
  12. // TODO Auto-generated method stub
  13. System.out.println("当前bean的名字:" + name); // 输出:red
  14. }
  15. // StringValueResolver解析占位符
  16. @Override
  17. public void setEmbeddedValueResolver(StringValueResolver resolver) {
  18. // TODO Auto-generated method stub
  19. String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
  20. System.out.println("解析的字符串:" + resolveStringValue); // 输出:你好Windows 10 我是360
  21. }
  22. }

image.png

5、@Profile环境搭建

  1. /**
  2. * Profile:
  3. * Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
  4. *
  5. * 开发环境、测试环境、生产环境;
  6. * 数据源:(/A)(/B)(/C);
  7. *
  8. * @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
  9. *
  10. * 1、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
  11. * 2、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
  12. * 3、没有标注环境标识的bean在,任何环境下都是加载的;
  13. */
  14. @PropertySource("classpath:/dbconfig.properties")
  15. @Configuration
  16. public class MainConfigOfProfile implements EmbeddedValueResolverAware{
  17. @Value("${db.user}")
  18. private String user;
  19. private StringValueResolver valueResolver;
  20. private String driverClass;
  21. @Bean
  22. public Yellow yellow(){
  23. return new Yellow();
  24. }
  25. @Profile("test")
  26. @Bean(destroyMethod = "testDataSource")
  27. public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
  28. ComboPooledDataSource dataSource = new ComboPooledDataSource();
  29. dataSource.setUser(user);
  30. dataSource.setPassword(pwd);
  31. dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
  32. dataSource.setDriverClass(driverClass);
  33. return dataSource;
  34. }
  35. @Profile("dev")
  36. @Bean(destroyMethod = "devDataSource")
  37. public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
  38. ComboPooledDataSource dataSource = new ComboPooledDataSource();
  39. dataSource.setUser(user);
  40. dataSource.setPassword(pwd);
  41. dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");
  42. dataSource.setDriverClass(driverClass);
  43. return dataSource;
  44. }
  45. @Profile("prod")
  46. @Bean(destroyMethod = "prodDataSource")
  47. public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
  48. ComboPooledDataSource dataSource = new ComboPooledDataSource();
  49. dataSource.setUser(user);
  50. dataSource.setPassword(pwd);
  51. dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515");
  52. dataSource.setDriverClass(driverClass);
  53. return dataSource;
  54. }
  55. // 值解析器
  56. @Override
  57. public void setEmbeddedValueResolver(StringValueResolver resolver) {
  58. // TODO Auto-generated method stub
  59. this.valueResolver = resolver;
  60. // 解析db.driverClass的值
  61. driverClass = valueResolver.resolveStringValue("${db.driverClass}");
  62. }
  63. }
  1. -- dbconfig.properties
  2. db.user=root
  3. db.password=123456
  4. db.driverClass=com.mysql.jdbc.Driver

6、@Profile根据环境注册bean

  1. //1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
  2. //2、代码的方式激活某种环境;
  3. @Test
  4. public void test01(){
  5. //1、创建一个applicationContext
  6. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
  7. //2、设置需要激活的环境
  8. applicationContext.getEnvironment().setActiveProfiles("dev");
  9. //3、注册主配置类
  10. applicationContext.register(MainConfigOfProfile.class);
  11. //4、启动刷新容器
  12. applicationContext.refresh();
  13. String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
  14. for (String string : namesForType) {
  15. System.out.println(string);
  16. }
  17. Yellow bean = applicationContext.getBean(Yellow.class);
  18. System.out.println(bean);
  19. applicationContext.close();
  20. }

image.png

五、AOP原理


六、声明式事务


七、扩展原理


八、创建Spring容器 - 源码