@Configuration
配置类==配置文件,告诉Spring这是一个配置类
@Bean
给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
注册到Spring容器中的默认是方法名,如果用value进行设置,则使用的是value的值
例: @Bean(value = "process") public Person process01(){ return new Person("lisi",20); }
给容器中注册组件; 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工厂创建bean @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); }
//创建一个Spring定义的FactoryBean public class ColorFactoryBean implements FactoryBean<Color> { //返回一个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; } }
初始化和销毁
1)、指定初始化和销毁方法; 通过@Bean指定init-method和destroy-method; 例: @Bean(initMethod = "init",destroyMethod = "detory") public Car car(){ return new Car(); }
public 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..."); } } 2)、通过让Bean实现InitializingBean(定义初始化逻辑), DisposableBean(定义销毁逻辑); 例: //定义扫描 @Component public 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..."); } }
3)、可以使用JSR250; @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法 @PreDestroy:在容器销毁bean之前通知我们进行清理工作 例: @Component public class Dog implements ApplicationContextAware { //@Autowired private ApplicationContext applicationContext; 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..."); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // TODO Auto-generated method stub this.applicationContext = applicationContext; } }
4)、BeanPostProcessor【interface】:bean的后置处理器; 在bean初始化前后进行一些处理工作; postProcessBeforeInitialization:在初始化之前工作 postProcessAfterInitialization:在初始化之后工作 Spring底层对 BeanPostProcessor 的使用; bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor; 例: /** * 后置处理器:初始化前后进行处理工作 * 将后置处理器加入到容器中 */ @Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("postProcessBeforeInitialization..."+s+"=>"+o); return o; } @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("postProcessAfterInitialization..."+s+"=>"+o); return o; } }
@ComponentScan
指定要扫描的包 excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件 includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件 FilterType.ANNOTATION:按照注解 FilterType.ASSIGNABLE_TYPE:按照给定的类型; FilterType.ASPECTJ:使用ASPECTJ表达式 FilterType.REGEX:使用正则指定 FilterType.CUSTOM:使用自定义规则
例:
@ComponentScans( value = { @ComponentScan(value="com.myjiang",includeFilters = { @ComponentScan.Filter(type=FilterType.ANNOTATION,classes={Controller.class}), @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}), // @ComponentScan.Filter(type= FilterType.CUSTOM,classes={MyTypeFilter.class}) },useDefaultFilters = false) } )
@Value
使用@Value赋值
1、基本数值 2、可以写SpEL; #{} 3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值)
例: @Value("张三") private String name; @Value("#{20-2}") private Integer age; @Value("${person.nickName}") private String nickName;
@Import
往容器中导入组件,不使用@Bean。id默认是组件的全类名
例:
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
Color.class,Red.class:把普通类注入到Spring容器中
MyImportSelector.class:收集需要导入的配置类实现ImportSelector 接口
com.myjiang.bean.Blue:需要注册进容器的类
com.myjiang.bean.Yellow:需要注册进容器的类
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.myjiang.bean.Blue","com.myjiang.bean.Yellow"}; } }
MyImportBeanDefinitionRegistrar.class:把所有需要添加到容器中的bean;调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
AnnotationMetadata:当前类的注解信息
BeanDefinitionRegistry:BeanDefinition注册类;
@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); } }
@Conditional
类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
例:
此注解可写在类上,写在类上必须是对应条件的bean才能被注入,写在方法上对应bean在相应条件下才能被注入,详情见代码
/** * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean * * 如果系统是windows,给容器中注册("bill") * 如果是linux系统,给容器中注册("linus") */ @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); }
@Scope
调整作用域 不写默认是单实例的 prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。 每次获取的时候才会调用方法创建对象; singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。 以后每次获取就是直接从容器(map.get())中拿, request:同一次请求创建一个实例 session:同一个session创建一个实例
@Lazy
单实例bean:默认在容器启动的时候创建对象; 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;
例:
//@Scope("prototype") @Lazy @Bean("person") public Person person(){ System.out.println("给容器中添加Person...."); return new Person("张三", 25); }
@component
把普通pojo实例化到spring容器中
@Component与@Bane的区别 两者都可以通过@Autowired装配 Bean 需要在配置类中使用,即类上需要加上@Configuration注解 如果你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component注解的,因此就不能使用自动化装配的方案了,但是我们可以使用@Bean,当然也可以使用XML配置。
@PropertySource
使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值
例:
@PropertySource("classpath:/person.properties") @Configuration public class MainConfigOfPropertyValues { @Bean public Person person(){ return new Person(); } }
@Value("${person.nickName}") private String nickName;
自动装配
* 自动装配; * 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;