Spring三种对象创建方式
1. 无参构造
首先我们先创建一个User类
public class User { private String name; private int age; public User() { System.out.println("无参构造方法"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
在spring的环境配置文件里配置
<bean name="user" class="cn.it.bean.User"></bean>
2. 静态工厂
创建一个UserFactory类,代码如下
public class UserFactory { public static User createUser() { System.out.println("静态工厂"); return new User(); } }
在配置文件里配置
<!-- 调用静态工厂 --> <bean name="user2" class="cn.it.create.UserFactory" factory-method="createUser"/>
3. 实例工厂
在上面的UserFactory改成如下代码
public class UserFactory { public static User createUser() { System.out.println("静态工厂"); return new User(); } public User createUser2() { System.out.println("实例工厂"); return new User(); } }
在配置文件里配置
<!-- 调用实例工厂 --> <bean name="user3" factory-bean="userFactory" factory-method="createUser2"></bean> <bean name="userFactory" class="cn.it.create.UserFactory"></bean>
上面三种创建方式已经准备好了,接下来我们写一个测试类
public class Demo { @Test //创建方法一:空参构造 public void fun1() { //每次容器启动就会创建容器中所配置的所有对象 ApplicationContext as = new ClassPathXmlApplicationContext("cn/it/create/applicationContext.xml"); User user = (User) as.getBean("user"); System.out.println(user); } @Test //创建方法二:静态工厂 public void fun2() { //每次容器启动就会创建容器中所配置的所有对象 ApplicationContext as = new ClassPathXmlApplicationContext("cn/it/create/applicationContext.xml"); User user = (User) as.getBean("user2"); System.out.println(user); } @Test //创建方法二:实例工厂 public void fun3() { //每次容器启动就会创建容器中所配置的所有对象 ApplicationContext as = new ClassPathXmlApplicationContext("cn/it/create/applicationContext.xml"); User user = (User) as.getBean("user3"); System.out.println(user); } }
Bean的装配方式
1. 基于XML的装配
首先创建一个实体类User
package com.iteima.assemable; import java.util.List; public class User { private String username; private Integer password; private List<String> list; /** * 1 使用构造注入 * 1.1 提供带所有参数的有参构造方法 */ public User(String username, Integer password, List<String> list) { this.username = username; this.password = password; this.list = list; } /** * 2 使用设置注入 * 2.1 提供默认空参数构造方法 * 2.2 为所有属性提供setter方法 */ public User(){ super(); } 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; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password=" + password + ", list=" + list + '}'; } }
创建bean配置文件
<?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"> <!--1.使用构造注入方式装配User实例--> <!-- public User(String username, Integer password, List<String> list)--> <bean id="user1" class="com.iteima.assemable.User"> <constructor-arg index="0" value="tom"/> <constructor-arg index="1" value="123456"/> <constructor-arg index="2"> <list> <value>"constructorvalue1"</value> <value>"constructorvalue2"</value> </list> </constructor-arg> </bean> <!--2.使用设值注入方式装配User实例--> <bean id="user2" class="com.iteima.assemable.User"> <property name="username" value="张三"></property> <property name="password" value="654321"></property> <!--注入list集合--> <property name="list"> <list> <value>"setlistvalue1"</value> <value>"setlistvalue2"</value> </list> </property> </bean> </beans>
创建一个测试类
package com.iteima.assemable; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class XmlBeanAssembleTest { public static void main(String[] args) { //加载配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); //构造方式输出结果 System.out.println(applicationContext.getBean("user1")); //设值方式输出结果 System.out.println(applicationContext.getBean("user2")); } }
2. 自动装配
虽然使用注解的方式装配Bean,在一定程度上减少了配置文件的代码量,但是也有企业项目中,是没有使用注解方式开发的,那么有没有什么办法既可以减少代码量,又能够实现Bean的装配呢?
答案是肯定的,Spring的<bean>元素中包含一个autowire属性,我们可以通过设置autowire属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动地注入到其他Bean的Propert中。</bean>
引用类型的自动注入:spring框架根据某些规则可以给引用类型赋值,不用你在给引用类型赋值了。
使用的规则常用的是byName,byType。
- byName(按名称注入):Java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。</bean>
- 语法:
<bean id="xx" class="yyy" autowire="byName"> 简单类型属性赋值 </bean>
byType(按类型注入):Java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性是同源就是一类的意思:</bean>
- Java类中引用类型的数据类型和bean的class的值是一样的。
- Java类中引用类型的数据类型和bean的class的值父子类关系的。
- Java类中引用类型的数据类型和bean的class的值接口和实现类关系的。
- 语法:
<bean id="xx" class="yyy" autowire="byType"> 简单类型赋值 </bean>
3. 基于注解的装配
组件扫描器
声明组件扫描器(component-scan),组件就是Java对象
- base-package:指定注解在你的项目中的包名。
- component-scan工作方式:spring会扫描遍历base-package指定的包,把包中和子包中的所有
类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。
<context:component-scan base-package="com.ithime.bean"/>
注解 | 作用 |
---|---|
@Component | 可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应的类上即可。 |
@Repository | 用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component相同。 |
@Service | 通常作用在业务层(Service层),用于将业务的类标识为Spring中的Bean,其功能与@Component相同。 |
@Controller | 通常作用在控制层(如SpringMVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。 |
@Autowired | 用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。 |
补充:
@Component:创建对象的,等同于<bean>的功能</bean>
属性:value就是对象的名称,也就是bean的id值,value的值是唯一的,创建的对象在整个spring
容器中就一个。
位置:在类的上面。
@Component(value = "myStudent")等同于
<bean id="myStudent" class="com.ithime.bean.Student"/>spring中和@Component功能一致,创建对象的注解还有:
- @Repository(用在持久层类的上面):放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的。
- @Service(用在业务层类的上面):放在Service的实现类上面,创建Service对象,Service对象做业务处理,可以有事务等功能表的。
- @Controller(用于控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果。
以上三个注解的使用语法和@Component一样的,都能创建对象,但是这三个注解还有额外的功能。