zoukankan      html  css  js  c++  java
  • 重新学习Spring注解——ICO

    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-小结

  • 相关阅读:
    【LOJ】#6432. 「PKUSC2018」真实排名
    【Codechef】BB-Billboards
    【BZOJ】4361: isn
    【BZOJ】4380: [POI2015]Myjnie
    【BZOJ】4292: [PA2015]Równanie
    【LOJ】#121. 「离线可过」动态图连通性
    【BZOJ】4025: 二分图
    【LOJ】#2230. 「BJOI2014」大融合
    【SPOJ】QTREE6-Query on a tree VI
    小白初理解树状数组
  • 原文地址:https://www.cnblogs.com/gzhcsu/p/11415782.html
Copyright © 2011-2022 走看看