java显示装配适用于第三方库的组件装配,在这个时候对于第三方库是不能加@Component注解的,其通常为打包好的class文件的集合体,在引用其时一般是不能修改器源码的其源码的,此时需要生成Bean需要手动包装,也就是通过显示配置来实现目的。
一、创建代码
创建People父类:
/*** @author FCmmmmmm**/
public interface People {
public abstract void sayHello();
}
创建Teacher子类:
/*** @author FCmmmmmm**/
public class Teacher implements People {
@Override
public void sayHello() {
}
}
解释: 模拟第三方库,上述为第三方库的源码,不接受修改,也就是不能在Teacher类的头上添加@Component等注解实现自动装配的。类似于hibernate,nybaties等实现通过bean生成现成的template直接使用就可以了,这些通常也是通过xml,javaBean等显示装配的(
仔细详想想是不是也可以通过spring封装java原生JDBC成为bean)
创建Bean:
/*** @author FCmmmmmm**/
@Configuration
public class PeopleConfig {
@Bean
public People creatPeople() {
return new Teacher();
}
/*public People getPeople() {return new Teacher();}*/
/*@Beanpublic ClassRoom getClassRoom() {Teacher teacher=(Teacher)creatPeople();return new ClassRoom(teacher);} */
/*@Beanpublic ClassRoom dds() {Teacher teacher=(Teacher)getPeople();return new ClassRoom(teacher);} */
}
Configuration注解是必不可少的《》《》
拓展( 这里通过产生的People是唯一的,只有一个实例(Bean的使用一般都是单例模式的)。)
测试:
/*** @author FCmmmmmm**/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=PeopleConfig.class)
public class TestS {
@Autowired
private People people;
@org.junit.Test
public void dodo() {
//ClassRoom room3=new PeopleConfig().getClassRoom();
if(people!=null) {
System.out.println("我创建了一个people");
}
}
结果:
简单的显示装配就完成了(这种bean创建方式在SpringBoot中很常见),mybatis,redis等就是通过这种显示装配的方式配置的,只不过通常在xml里面配置而已。
二、个人思考部分
使用时肯定不是这么简单,通常要构建多个bean结合然后生成一个新的Bean
构建一个ClassRoom类,每个classroom都有一个teacher坐镇
/*** @author FCmmmmmm**/
public class ClassRoom {
private Teacher teacher1;
ClassRoom(Teacher teacher){
this.teacher1=teacher;
}
}
配置类:
/*** @author FCmmmmmm**/
@Configuration
public class PeopleConfig {
@Bean
public People creatPeople() {
return new Teacher();
}
/*public People getPeople() {return new Teacher();}*/
@Bean
public ClassRoom getClassRoom() {
//Teacher teacher=(Teacher)creatPeople();return new ClassRoom((Teacher)creatPeople());
}
}
现在是调用creatPeople()再转换为Teacher的形式构造注入一个Teacher的实例
拓展( creatPeople()每次都会返回一个people而且返回的people的地址都是相同的,也就是 new Teacher()只执行了一次,执行一次过后,容器中已经有关于People的实例就不会再重新创建新的实例 )
验证:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=PeopleConfig.class)
public class TestS {
@Autowired
private ClassRoom room;
@Autowired
private ClassRoom room2;
@org.junit.Test
public void dodo() {
if(room!=null&&room==room2) {
System.out.println("121321");
}
/*if(room3!=null) {System.out.println("1231231333333333333");}*/
}
}
结果:
他们是相等的,room和room2的地址是相等的并且其包含的teacher的地址也是相同的
不明点:
如下:
/*** @author FCmmmmmm**/
@Configuration
public class PeopleConfig {
@Bean
public People creatPeople() {
return new Teacher();
}
/*public People getPeople() {return new Teacher();}*/
@Bean
public ClassRoom getClassRoom() {
Teacher teacher=(Teacher)creatPeople();
return new ClassRoom(teacher);
}
@Bean
public ClassRoom dds() {
Teacher teacher=(Teacher)creatPeople();
return new ClassRoom(teacher);
}
}
我同时创建了两个bean但他们都会返回一个ClassRoom的实例
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=PeopleConfig.class)
public class TestS {
@Autowired
private ClassRoom room;
/*@Autowiredprivate ClassRoom room2;*/
@org.junit.Test
public void dodo() {
if(room!=null) {
System.out.println("121321");
}
/*if(room3!=null) {System.out.println("1231231333333333333");}*/
}
}
spring提示错误找到两个bean,它们的id应该是不同的,但为什么会出现这样的错误还不是很明白。
解决办法:
将@Autowire换成@Resource(name="dds")并指定name即可解决问题
不同name导入的classroom的地址是不同的但是里面的teacher的地址是相同的
结论:spring Bean的单例是建立在相同的BeanId的基础上