重新学习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-小结

posted on 2019-08-26 23:44  betterLearing  阅读(386)  评论(0编辑  收藏  举报