Bean的实例化
再Spring中想要实例化bean,有三种方式,分别为构造器实例化,静态工厂方式实例化和实例工厂方式实例化。
构造器实例化
直接用对应类的无参构造方法来实例化对象。演示代码如下
package com.itheima.instance.constructor;
public class Bean1 {
public Bean1() {
System.out.println("构造器实例化Bean1");
}
}
<bean id="bean1" class="com.itheima.instance.constructor.Bean1"/>
静态工厂方式实例化
想要获得一个对象的实例,通过另一个对象的静态方法进行获取。演示代码如下
package com.itheima.instance.static_factory;
public class Bean2 {
public Bean2() {
System.out.println("静态工厂方式实例化Bean2");
}
}
package com.itheima.instance.static_factory;
public class MyBean2Factory {
public static Bean2 createBean() {
return new Bean2();
}
}
<bean id="bean2" class="com.itheima.instance.static_factory.MyBean2Factory" factory-method="createBean"/>
实例工厂方式实例化
想要实例化某个对象,则用另一个对象的非静态方法获取该实例。此方式跟静态工厂方式实例化不同的是xml文件配置中,要配置来获取该实例的对象。演示代码如下
package com.itheima.instance.factory;
public class Bean3 {
public Bean3() {
System.out.println("实例工厂方式实例化Bean3");
}
}
<bean id="myBean3Factory" class="com.itheima.instance.factory.MyBean3Factory"/>
<bean id="bean3" factory-bean="myBean3Factory" factory-method="createBean"/>
最后可以写一个类来测试上面三种实例化方式
package com.itheima.instance;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestInstance {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(applicationContext.getBean("bean1"));
System.out.println(applicationContext.getBean("bean2"));
System.out.println(applicationContext.getBean("bean3"));
}
}
Bean的作用域
再配置bean时,可以指定scope的值来设置其作用域,scope有七个作用域
* singleton:在Spring容器中只有一个实例,无论有多少个对象引用它,始终指向同一个对象。这是scope的默认值。
* prototype:每次通过Spring容器获取的,都会创建一个新的实例
* request:在一次HTTP请求中,容器返回该Bean的同一实例
* session:在一次HTTP Session中,容器返回该Bean的同一实例
* globalSession:在一个全局的HTTP Session中,容器返回该Bean的同一实例
* application:为每个ServletContext对象创建一个实例
* websocket:为每个websocket对象创建一个实例
Bean的生命周期
- 根据配置情况调用Bean的构造方法或工厂方法实例化Bean
- 利用依赖注入完成Bean中所以属性的配置注入
- 如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值
- 如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory方法传入当前工厂实例的引用
- 如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext方法传入当前ApplicationContext的引用
- 如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始方法postProcessBeforeInitailzation对Bean进行加工操作
- 如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet方法
- 如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法
- 如果有BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialzation,此时,Bean已经可以被应用系统使用了
- 如果Bean的作用范围为singleton,则将该Bean放入IOC的缓存池里面,触发Spring对其生命周期的管理。如果是prototype,则由调用者管理该Bean的生命周期
- 如果实现了DisposableBean接口,则Spring会调用destroy方法将Spring中的Bean销毁。如果配置文件中用destory-method指定了Bean的销毁方法,则调用该方法进行销毁
Bean的装配方式
基于XML的装配
在xml文件里面通过 <bean> 标签进行装配Bean。代码演示可参考我的另一篇博客。
bean标签的常用属性有如下:
* id:是一个Bean的唯一标识符
* name:为bean指定名称,可以指定多个,用逗号或者分号隔开
* class:指定Bean的具体实现类,必须是一个完整的类名
* scope:设定Bean实例的作用域
* autowire:通过设置其值,可以将一个Bean自动地注入到其他Bean地Property中。它有五个值,default是由beans标签地default-autowire属性值来确定,byName是根据名称自动装配,byType是根据属性地数据类型自动装配,constructor是更具构造参数的数据类型,进行byType模式的自动装配,no是不使用自动装配
bean标签的子元素和子元素的属性有如下:
* constructor-arg:用来设置传入构造参数,index属性从0开始,依次表示构造参数,value属性表示该构造参数的值,也可以用ref属性引用
* property:用于调用bean中的setter方法来完成属性赋值。name属性指定Bean中相应的属性名,value属性设置其值,或者用ref来进行引用
* ref:<property>、<constructor-arg>等元素的属性或者子元素,可以引用一个实例值
* list:用来封装List或者数组类型的依赖注入
* set:用来封装Set类型属性的依赖注入
* map:用来封装Map类型属性的依赖注入
* entry:<map>的子元素,用来设置一个键值对,其key属性指定字符串类型的键值,ref或者value子元素指定其值,也可以通过value-ref或value属性指定其值。
下面是相关的演示代码
bean类的代码
package com.itheima.assemble;
import java.util.List;
import java.util.Map;
public class User {
private String username;
private Integer password;
private List<String> list;
private Map<String, Integer> relations;
public User() {}
public User(String username, Integer password, List<String> list, Map<String, Integer> relations) {
this.username = username;
this.password = password;
this.list = list;
this.relations = relations;
}
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 void setRelations(Map<String, Integer> relations) {
this.relations = relations;
}
public User(String username, Integer password, List<String> list) {
this.username = username;
this.password = password;
this.list = list;
}
@Override
public String toString() {
return "username="+username+";password="+password+";list="+list+";relations="+relations.get("key1");
}
}
在xml中的配置
<?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.itheima.assemble.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="123456"/>
<constructor-arg index="2">
<list>
<value>list1</value>
<value>list2</value>
</list>
</constructor-arg>
<constructor-arg index="3">
<map>
<entry key="key1" value="1"/>
</map>
</constructor-arg>
</bean>
<bean id="user2" class="com.itheima.assemble.User">
<property name="username" value="张三"/>
<property name="password" value="123456"/>
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<property name="relations">
<map>
<entry key="key1" value="1"/>
</map>
</property>
</bean>
</beans>
测试类
package com.itheima.assemble;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/itheima/assemble/user.xml");
System.out.println(applicationContext.getBean("user1"));
System.out.println(applicationContext.getBean("user2"));
}
}
基于注解的装配
使用注解配置需要spring-aop的jar包,常用的注解有如下:
* @Compent:描述Spring中的Bean
* @Repository:描述数据层的Bean
* @Service:描述业务层的Bean
* @Controller:描述控制层的Bean
以上的四个注解相当于<bean id=“ ” class=“ ”>,功能是一样的,只是意义不同
- @Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注
- @Resource:用于对Bean的属性变量、属性的setter方法及构造方法进行标注
以上两个注解功能一样,其区别在于@Autowired默认按照Bean类型装配,而@Resource是按照Bean实例名称,其有两个属性,name和type,那么是按照Bean实例名称装配,type是按照Bean类型进行装配,其相当与<property name=” ” ref=” “>
以下是演示代码
package com.itheima.annotation;
public interface UserDao {
public void save();
}
package com.itheima.annotation;
import org.springframework.stereotype.Repository;
@Repository("userDao")
public class UserDaoImpl implements UserDao{
public void save() {
System.out.println("userdao...save...");
}
}
package com.itheima.annotation;
public interface UserService {
public void save();
}
package com.itheima.annotation;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService{
@Resource(name = "userDao")
private UserDao userDao;
public void save() {
this.userDao.save();
System.out.println("userservice...save...");
}
}
在xml文件中的配置如下,<context:annotation-config/>用于开启注解处理器。而<context:component-sacn base-package=”Bean所在的包路径”/>是用来对包路径下的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"
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">
<context:annotation-config/>
<context:component-scan base-package="com.itheima.annotation"/>
</beans>
这是测试类
package com.itheima.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAnnotation {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com.itheima.annotation.testAnnotation.xml");
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
userService.save();
}
}