【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】
之前我们又完成了使用“工厂” 去创建bean 对象
现在有个新问题又来了
现在的加载方式,有xml 配置文件,也有配置类,如果说我现在有一个十年前写的程序,它是用的配置文件加载的bean, 但是现在要上新功能,用注解写的,如果不能修改配置文件,那咋办?【典型的系统迁移问题:如何在一个新的注解开发的项目中使用老的配置文件的方式?可以实现吗?】
【答案是当然的】
来一个新的配置类
package com.dingjiaxiong.config;
import com.dingjiaxiong.bean.DogFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
/**
* ClassName: SpringConfig32
* date: 2022/10/24 13:40
*
* @author DingJiaxiong
*/
public class SpringConfig32 {
}
其实啥也没有
来一个新的运行类去加载32 这个配置类
package com.dingjiaxiong.app;
import com.dingjiaxiong.config.SpringConfig3;
import com.dingjiaxiong.config.SpringConfig32;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* ClassName: App3
* date: 2022/10/24 13:42
*
* @author DingJiaxiong
*/
public class App32 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig32.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
直接运行看看效果
OK,没啥问题
现在就来修改32 这个配置类,让它可以去加载到我们使用 xml 配置文件的方式做的bean
其实特简单,一个注解
package com.dingjiaxiong.config;
import com.dingjiaxiong.bean.DogFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
/**
* ClassName: SpringConfig32
* date: 2022/10/24 13:40
*
* @author DingJiaxiong
*/
@ImportResource("applicationContext1.xml")
public class SpringConfig32 {
}
这是啥意思呢?就是说假定我们32 这个配置类还没写完,我现在就想拿xml 配置中的东西放到我们的配置类中
OK,直接运行
效果很明显,都上来了
这就是在现在的配置类中导入原始的配置文件的做法
回顾一下
之前我们提了一下,@Configuration 这个注解和 @Component 这个注解很像,但是是假的
看看两个注解的源码:
@Component :
@Configuration:
注意看这最后一个【研究一下】
再来一个新的配置类
package com.dingjiaxiong.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* ClassName: SpringConfig33
* date: 2022/10/24 13:40
*
* @author DingJiaxiong
*/
@Configuration
public class SpringConfig33 {
}
还是一个空壳
再来一个新的运行类
package com.dingjiaxiong.app;
import com.dingjiaxiong.config.SpringConfig32;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* ClassName: App33
* date: 2022/10/24 13:42
*
* @author DingJiaxiong
*/
public class App33 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig33.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
直接运行看看效果
OK, 没啥问题
看看这个bean 的类型
System.out.println("=========================");
System.out.println(ctx.getBean("springConfig33"));
直接运行看看
这一串什么玩意儿
意思就是SpringConfig33 其实是一个代理对象
现在修改一下33 配置类
再次运行
效果很明显,那一串东西没了,就说明现在这个对象,已经不是一个代理对象了,就成了一个原始对象
【所以这玩意儿的作用是什么?】
我们在33 配置类中定义一个 bean
package com.dingjiaxiong.config;
import com.dingjiaxiong.bean.Cat;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* ClassName: SpringConfig33
* date: 2022/10/24 13:40
*
* @author DingJiaxiong
*/
@Configuration(proxyBeanMethods = false)
public class SpringConfig33 {
@Bean
public Cat cat(){
return new Cat();
}
}
直接再次运行
OK, 这没啥,上来了一个bean 对象
现在我们直接用33 这个配置类,去调用这个方法
package com.dingjiaxiong.app;
import com.dingjiaxiong.config.SpringConfig32;
import com.dingjiaxiong.config.SpringConfig33;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* ClassName: App33
* date: 2022/10/24 13:42
*
* @author DingJiaxiong
*/
public class App33 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig33.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
System.out.println("=========================");
SpringConfig33 springConfig33 = ctx.getBean("springConfig33", SpringConfig33.class);
System.out.println(springConfig33.cat());
System.out.println(springConfig33.cat());
System.out.println(springConfig33.cat());
}
}
调了三次,而且把proxyBeanMethods 属性值改为了 true
直接运行看看
可以看到,就是普通的bean对象,而且是单例的,即同一个对象
如果改成false
好家伙,很明显,现在就不是单例的了【就成了完全不同的三个对象】
意思就是如果proxyBeanMethods 属性为true,我们在运行对应的方法时,这个方法如果曾经在Spring 容器中加载过bean,那么我们再调,就是直接从容器中去拿了,而不是重新创建
如果属性值为false【不创建代理对象】,就是使用当前类对象去执行它里面的方法,所以才有了三个不同的cat 对象【这就是true 和 false 的区别】
【默认是true,即创建代理对象】
看懂了这个,就可以解释我们前面遇到过的一个事情,学mq 的时候
我把这个注解一关,下面的东西就不能用了,但是我一开
因为proxyBeanMethods 属性默认为true,所以这就保证了我们每次都操作的 是同一个队列
如果我明着写成配成false
这样就绑不对了,压根儿都不是同一个了
OK,差不多就是这样
回顾一下
使用proxyBeanMethods=true可以保障调用此方法得到的对象是从容器中获取的而不是重新创建的