一、@Scope 设置组件作用域
- 默认是单实例
- prototype 每次获取的时候才会调用方法创建bean
- singleton IoC容器启动会调用方法创建对象放到IoC容器中,这样每次获取都是相同的
- request
- session
二、@Lazy 懒加载
懒加载: 容器启动不创建对象,第一次获取bean的时候才创建对象,并初始化
三、@Conditional 按条件注册Bean
@Conditional 按照一定的条件判断,满足条件给容器中注册bean
四、给容器中注册组件
1. @ComponentScan包扫描+组件标注注解(@Controller/@Service/@Reponitory/@Component)
2. @Configuration + @Bean[导入第三方包里面的组件]
3. @Import[快速给容器中的导入一个组件]
- @Import(要导入到容器中的组件), 容器中就会自动注册这个组件,id默认是全类名
@Configuration
@Import(value = {Test01.class, Test02.class})
public class MainConfig {
@Bean(value = "person")
public Person person01(){
return new Person("zhangsan", 23);
}
}
- ImportSelector接口: 返回需要导入的组件的全类名
// 返回需要导入的组件
public class MyImportSelector implements ImportSelector {
/**
* AnnotationMetadata 当前标注@Import注解类的所有注解信息
*
* @param importingClassMetadata
* @return
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 不要返回null值,会报空指针异常
return new String[]{"com.aloneness.bean.Test03", "com.aloneness.bean.Test04"};
}
}
@Configuration
@Import(value = {Test01.class, Test02.class, MyImportSelector.class})
public class MainConfig {
@Bean(value = "person")
public Person person01(){
return new Person("zhangsan", 23);
}
}
- ImportBeanDefinitionRegistrar
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* 把所有需要添加到容器中的bean, 调用BeanDefinitionRegistry.registerBeanDefinition() 手工注册进来
*
* @param importingClassMetadata AnnotationMetadata 当前类的注册信息
* @param registry BeanDefinitionRegistry BeanDefinition的注册类
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.aloneness.bean.Test03");
boolean definition1 = registry.containsBeanDefinition("com.aloneness.bean.Test04");
if(definition && definition1){
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Test05.class);
registry.registerBeanDefinition("test05", rootBeanDefinition);
}
}
}
@Configuration
@Import(value = {Test01.class, Test02.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
@Bean(value = "person")
public Person person01(){
return new Person("zhangsan", 23);
}
}
4. 使用Spring提供的FactoryBean(工厂Bean)
// 创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
// 返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
// true 是单实例 false 是多实例
@Override
public boolean isSingleton() {
return true;
}
}
@Configuration
@Import(value = {Test01.class, Test02.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
@Bean(value = "person")
public Person person01(){
return new Person("zhangsan", 23);
}
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
}
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
// 工厂Bean获取的是getObject()创建的对象
Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");
System.out.println(colorFactoryBean.getClass()); // class com.aloneness.bean.Color
// 如果需要获取工厂Bean,需要加上前缀&
Object colorFactoryBean1 = applicationContext.getBean("&colorFactoryBean");
System.out.println(colorFactoryBean1.getClass()); // class com.aloneness.bean.ColorFactoryBean
}
}
五、Bean的生命周期
Bean的生命周期: 创建---初始化---销毁的过程, 容器管理bean的生命周期
自定义初始化和销毁方法
构造(对象创建)
- 单实例:在容器启动的时候创建对象; 创建对象完成,并赋值好,调用初始化方法; 容器关闭的时候调用销毁方法
- 多实例:在获取Bean的时候创建对象; 调用初始化方法; 容器不会管理这个Bean,不会调用销毁方法
- 指定初始化和销毁方法,通过@Bean注解初始化和销毁
public class Car {
public Car(){
System.out.println("car constructor...");
}
public void init(){
System.out.println("car init()...");
}
public void destory(){
System.out.println("car destory()...");
}
}
@Configuration
public class MainConfigOfLifeCycle {
@Bean(initMethod = "init", destroyMethod = "destory")
public Car car(){
return new Car();
}
}
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器创建完成...");
applicationContext.close();
}
}
// 结果为
car constructor...
car init()...
容器创建完成...
car destory()...
- 通过InitializingBean、DisposableBean接口定义初始化,销毁方法
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat(){
System.out.println("cat...构造器...");
}
// 初始化, Bean创建完成,并赋值好后
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet...初始化...");
}
// 销毁方法
@Override
public void destroy() throws Exception {
System.out.println("destroy...销毁...");
}
}
@Configuration
@ComponentScan("com.aloneness.lifeCycle")
public class MainConfigOfLifeCycle {
}
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器创建完成...");
applicationContext.close();
}
}
// 结果为
cat...构造器...
afterPropertiesSet...初始化...
容器创建完成...
destroy...销毁...
- 可以使用JSR250
- @PostConstruct: 在bean创建完成并且属性赋值完成,来执行初始化方法
- @PreDestory: 在容器销毁Bean之前通知我们进行清理工作
@Component
public class Dog {
public Dog(){
System.out.println("Dog constructor...");
}
@PostConstruct
public void init(){
System.out.println("Dog...init...");
}
@PreDestroy
public void destroy(){
System.out.println("Dog...destory");
}
}
@Configuration
@ComponentScan("com.aloneness.lifeCycle")
public class MainConfigOfLifeCycle {
}
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器创建完成...");
applicationContext.close();
}
}
// 结果为
Dog constructor...
Dog...init...
容器创建完成...
Dog...destory
- BeanPostProcessor接口, Bean的后置处理器, 用来处理Bean创建前后的工作
- postProcessBeforeInitialization 在初始化之前工作
- postProcessAfterInitialization 在初始化之后工作
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* @param o bean实例
* @param s bean的名字
* @return 返回bean对象
* @throws BeansException
*/
@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;
}
}
// 结果为
cat...构造器...
postProcessBeforeInitialization...初始化前...cat-->com.aloneness.lifeCycle.Cat@101df177
afterPropertiesSet...初始化...
postProcessAfterInitialization...初始化后...cat-->com.aloneness.lifeCycle.Cat@101df177
@Value赋值
- 基本数值
- SpEL, #{}
- 配置文件的值 ${}
- 引入配置文件@PropertySource(value = {"classpath:person.properties"})
- @Value("${person.age}") 标注属性
自动装配
- @Autowired 自动注入
- 默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class)
- 如果找到多个相同的类型的组件,再将属性的名称作为组件的id去容器中查找
- @Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
- 默认一定要将属性赋值好, 否则会出错, 可以使用@Autowired(required = false), 但不推荐
- @Primary 让Spring进行装配Bean的时候, 首选这个Bean装配
- 还支持使用@Resource(JSR250) @Inject(JSR330) Java规范
- 自定义组件想要使用Spring容器底层的一些组件(applicationContext,BeanFactory,xxx)自定义组件实现xxxAware接口 xxxAware:功能使用xxxProcessor
@Profile
- Profile: Spring 为我们提供的可以根据当前的环境,动态的激活和切换一系列 组件的功能
-
- 命令行参数 -Dspring.profiles.active=test\dev\prod
-
- 使用代码的方式激活
@Configuration
public class MainConfigOfProfile {
@Profile("dev")
@Bean
public DataSource devDataSource() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("123456");
comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/myshop");
return comboPooledDataSource;
}
@Profile("prod")
@Bean
public DataSource prodDataSource() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("123456");
comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/myshop");
return comboPooledDataSource;
}
}