bean的装配通俗点就是依赖注入(spring的特点之一),再说通俗点就是类中属性的赋值,而这种赋值不是由我们直接在代码中赋值,而是通过在配置文件中配置值类实现的,给他起了一个高大上的名字,让我来说就是把赋值包装了一层还有一层呀。让我们一起看看这三种装配方式怎么实现的吧!!
1、基于XML的装配
基于xml的装配方式有俩种表现形式,在Java中,大家对类中属性赋值一般有俩种吧,第一种就是通过有参构造方法,第二种通过set方法吧,那么基于xml的装配本质也是通过这俩种方式,只不过由我们自己赋值交给spring容器赋值,这也体现了spring的特点嘛,控制反转(将本该属于开发者的权利放心的交给这个spring管理者,还是免费的哦),我们只需要在配置文件中配置几个节点就可以完成了,本质还是Java通俗的那俩种方法,只不过spring帮你封装了。先看代码:
//功能需求:就是能不能成功给User类中的属性赋值,通过spring框架。
package com.test;
import java.util.List;
public class User {
private String username;
private Integer password;
private List<String> list;
/**
* 使用构造注入
* 需要提供一个所有参数的有参构造。
**/
public User(String username, Integer password , List<String> list){
this.username = username;
this.password = password;
this.list = list;
}
/*
* 使用设值注入
* 必须提供一个无参构造方法
* 必须为你需要赋值的属性提供一个set方法
* */
public User(){
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(Integer password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
public String getUsername() {
return username;
}
public Integer getPassword() {
return password;
}
public List<String> getList() {
return list;
}
@Override
public String toString() {
return "User[username = " + username +
", password = " + password + ", list = " + list + "]";
}
}
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
//不使用spring来给属性赋值的Java代码,也是俩种方法
//通过构造器来给属性赋值
List<String> list = new ArrayList<>();
list.add("values1");
list.add("values2");
User user1 = new User("sam" ,456789,list);
System.out.println(user1.toString());
//方法二
User user2 = new User();
user2.setUsername("jack");
user2.setPassword(987654);
user2.setList(list);
System.out.println(user2.toString());
//spring框架给属性赋值的俩种方法,其实本质上也是用上面俩种方法,只不过绕了一个弯,你需要在配置文件中给属性赋值
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("com/config/ApplicationContext.xml");
//方法一:通过构造器给属性赋值,也就是高大上的Bean装配
System.out.println(applicationContext.getBean("user1"));
//方法二:通过set注入的方式给属性赋值
System.out.println(applicationContext.getBean("user2"));
}
}
//配置文件
/*
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user1" class="com.test.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="123456"/>
<constructor-arg index="2" >
<list>
<value>"constructorvalues1"</value>
<value>"constructorvalues2"</value>
</list>
</constructor-arg>
</bean>
<bean id="user2" class="com.test.User">
<property name="username" value="baby"/>
<property name="password" value="654321"/>
<property name="list">
<list>
<value>"value1"</value>
<value>"value2"</value>
</list>
</property>
</bean>
</beans>
*/
//结果
/*
User[username = sam, password = 456789, list = [values1, values2]]
User[username = jack, password = 987654, list = [values1, values2]]
User[username = tom, password = 123456, list = ["constructorvalues1", "constructorvalues2"]]
User[username = baby, password = 654321, list = ["value1", "value2"]]
*/
使用Java代码给属性赋值大家都应该会,使用spring来给属性赋值就要好好说明一下了,在spring中,为了给某一个类中属性赋值,spring提供了俩种方法,第一个是基于有参构造方法,你需要在配置文件中对应的bean下配置<constructor-arg>节点,里面有个index属性,对应类中有参构造中参数的位置,第一位的值时0,依次下去,Value就是你要给这个属性赋的值了,对于集合类来说,list集合用<list>标签,set集合用<set>标签,Map集合用<map>标签,都是有想对应的标签可以使用,然后在测试类中通过applicationContext对象获取到通过id为user1的bean实例化出来的对象中的属性是否成功赋值。结果当然是可以的了
第二种方式的话就是通过set方法了,spring把他封装成需要配置了,所以你要在配置文件中配置节点,使用set方式装配的话,需要在对应的bean节点下配置子节点<property> 其中name代表目标类中的属性名,Value肯定就是一个需要赋的值了。对于集合的话还是使用<list><set><map>等标签了。
其中只要记住,使用<constructor-arg>节点来装配属性的话肯定是构造器的方式,使用<property>节点是set装配属性的方式。
还有一个就是其中有个需要注意的地方就是Value和ref的属性,什么时候使用value,什么时候使用ref其实很好记忆,ref只能填写配置文件中存在的id值,value填写常量值。
2、基于annotion(注解)的装配
虽然使用基于xml的方式逻辑很清晰,但是当我们项目中的类有大量的需要在配置文件中配置的话,那配置文件中会存在很多的bean了,并且类中必定存在很多属性,存在属性那肯定需要使用到spring的装配咯,想想一下一个bean下面配置7,8行的装配,那10个bean,100个bean需要的篇幅有多大呢,这样就会显得太冗长,所以spring还提供了一种注解的方式类对bean中的属性进行装配,让我们一起来看看吧。先上代码后解释:
package com.test;
public interface UserDao {
void sava();
}
package com.test;
import org.springframework.stereotype.Repository;
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void sava() {
System.out.println("userDaoImpl save ....");
}
}
package com.test;
public interface UserService {
void save();
}
package com.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name = "userDao")
private UserDao userDao ;
@Override
public void save() {
userDao.sava();
System.out.println("userServiceImpl save ....");
}
}
package com.test;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller("userController")
public class UserControl {
@Resource(name = "userService")
private UserService userService;
public void sava(){
this.userService.save();
System.out.println("userController save ...");
}
}
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("com/config/ApplicationContext.xml");
UserControl userControl = (UserControl) applicationContext.getBean("userController");
userControl.sava();
}
}
//配置文件
/*
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--我们在类中使用了一些注解,要想要spring能够识别理解这些注解代表什么意义,还需要配置一下注解注解处理器-->
<!--注解处理器-->
<context:annotation-config></context:annotation-config>
<!--把需要的三个类以最基本bean的形式定义在这配置文件中,最基本的bean就是只有id和class俩个属性的bean-->
<bean id="userDao" class="com.test.UserDaoImpl"></bean>
<bean id="userService" class="com.test.UserServiceImpl"></bean>
<bean id="userController" class="com.test.UserControl"></bean>
<!--通过以上4行配置我们就可以得到正确的结果了,相比于不使用注解的方式,这配置已经节省了很多配置量了-->
<!--但是还是有人会觉得不够洁简,所以开发spring框架的人又提供了另外一种功能,扫描功能,能够我们直接省略bean的配置,看下面配置-->
<!--这一行配置能够顶替上面3个bean,而且spring框架会扫描 com.test包下的所有类,只要你配置了注解处理器他会去对包中每个注解识别处理-->
<!--如果你使用注解的方式来装配,那么以后你可以把写bean的代码也省略了,而这种方式也是我们项目最最最常用的,必须掌握且熟练运用的一种方式-->
<context:component-scan base-package="com.test"></context:component-scan>
</beans>
*/
//结果
/*
userDaoImpl save ....
userServiceImpl save ....
userController save ...
*/
//从结果可以知道,我们实现类中属性的赋值通过注解是成功的,而且注解配置这种方式也是最方便最常用的
在上面代码中,我使用了Repository,Service,Controller,Resource四个注解,前面三个注解其实差不多,只是为了区别这个类的类型。
我们是在相应的类上面写了@Repository("userDao")这个注解其实我是省略写的,不省略的话是@Repository(value = "userDao"),该注解是告诉Spring,让Spring创建一个名字叫“userDao”的UserDaoImpl实例。 Service和controller注解意思一样,而且想要spring引用这个类的话只需要在相应类属性上面添加@Resource(name ="userDao")引号中填写的是Value值。
3、自动装配
第三种自动装配其实没有第二种方法好,但是比第一种方法要轻便,第一种方法中我们不仅要写bean,而且我们得在bean节点下面配置属性装配的节点,而自动装配省略了这些子节点的编写,而是只需要在bean节点中加一个属性配置,这个属性是autowire,我们上面的代码中对UserServerImpl 和UserController类中的属性给一个set方法,然后去掉俩个类中属性上的Resource注解,现在需要属性配置的一共就是UserService类和UserController类,我再把配置文件的代码贴一下
//配置文件
/*
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--我们在类中使用了一些注解,要想要spring能够识别理解这些注解代表什么意义,还需要配置一下注解注解处理器-->
<!--注解处理器-->
<context:annotation-config></context:annotation-config>
<!--把需要的三个类以最基本bean的形式定义在这配置文件中,最基本的bean就是只有id和class俩个属性的bean-->
<bean id="userDao" class="com.test.UserDaoImpl" ></bean>
<bean id="userService" class="com.test.UserServiceImpl" autowire="byType"></bean>
<bean id="userController" class="com.test.UserControl" autowire="byType"></bean>
</beans>
*/
对比第二种的配置文件,其实只是在userService和userControllerbean中添加了属性autowire,byType这个值的含义代表这spring容器会根据属性类型去找相应的bean,例如这个userServiceImpl类中的属性为Userdao,他会找到Userdao的实现类UserdaoImpl,然后实例化得到一个UserdaoImpl的对象将这个对象装配给UserServiceImpl类总的属性userDao。userController类中也是一个意思。
最后讲几个我刚开始学会碰到的困惑:认为属性赋值都需要用spring的装配功能,其实这是没必要的,如果你一开始就需要给类中属性赋值为什么不直接赋值呢,还去绕个弯去配置文件总配置,或者写个注解出来,没必要,像普通类型就可以直接赋值呀,而不需要用到<constructor-arg>节点或者<property>去配置了,如果是类属性需要赋值的也可以直接赋值的,没必要去注解啥的,就是告诉大家,不是一定要去装配的,可以赋值的就像Java一样去赋值就可以了。
QQ:1156999375 有啥不懂的可以一起交流呀QAQ