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的基础上