前言
什么是bean的实例化?
通常我们使用spring管理java的对象,一般称这个java对象为一个实例化的bean。bean的实例化方式,实际上就是spring创建并管理java对象实例的方式
bean的实例化方式
在Java和Spring框架的上下文中,Bean的实例化是指创建Java对象(Bean)的过程。这个过程涉及到将Java类的定义(即类的字节码)转换成内存中实际可用的对象实例。在Spring框架中,Bean的实例化是Spring容器(也称为IoC容器)管理对象生命周期的一部分,它负责创建、配置、组装和管理这些对象。
Spring容器通过几种不同的方式来实例化Bean,包括但不限于以下几种:
1. 构造方法实例化
- 方式描述 :通过调用Java Bean类的构造方法来创建对象。默认情况下,Spring会调用Bean的无参数构造方法。如果Bean类中有多个构造方法,可以通过配置指定使用哪个构造方法,或者通过构造方法注入依赖。
- 应用场景:适用于大多数简单的Bean实例化场景,特别是当Bean的创建不依赖于其他Bean或复杂逻辑时。
2. 静态工厂方法实例化
- 方式描述 :通过调用静态工厂方法来创建Bean实例。这种方式需要在Spring配置文件中指定工厂类的静态方法。
- 应用场景:当Bean的创建过程比较复杂,或者Bean的创建依赖于一些静态的、不需要实例化的资源时,可以使用静态工厂方法。
3. 实例工厂方法实例化
- 方式描述 :通过调用实例工厂的方法来创建Bean实例。这种方式需要首先创建工厂Bean的实例,然后通过该实例的方法来创建目标Bean。
- 应用场景:当Bean的创建依赖于其他Bean的实例时,或者当Bean的创建过程需要复杂的逻辑处理时,可以使用实例工厂方法。
4. Spring的FactoryBean接口实例化
- 方式描述 :通过实现Spring的FactoryBean接口来创建Bean实例。FactoryBean接口提供了getObject()方法,Spring容器在调用该方法时返回Bean实例。这种方式允许开发者在Bean的创建过程中进行更复杂的操作,如懒加载、代理创建等。
- 应用场景:当需要更细粒度的控制Bean的创建过程,或者需要返回Bean的代理对象时,可以使用FactoryBean接口。
5. 反射实例化(非Spring特有)
- 方式描述:使用Java反射机制来实例化Java Bean对象。通过Class类的newInstance()方法或Constructor类的newInstance()方法可以动态创建对象。
- 应用场景:在不需要Spring框架的情况下,或者当需要动态地根据类名创建对象时,可以使用反射实例化。
小结
Bean的实例化方式多种多样,每种方式都有其特定的应用场景和优势。在实际开发中,应根据具体需求和开发环境选择合适的实例化方式。同时,随着Spring框架的不断发展,未来还可能出现更多新的实例化方式。
bean的四种实例化方式的案例演示
bean本质上是一个对象,是spring操作类的构造方法创建的(不论这个构造方法是私有还有共有),底层通过反射完成;并且调用的是无参的构造方法。
准备工作
创建一个maven项目,导入spring相关依赖包
XML
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
在resources中配置spring配置文件
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">
</beans>
构造方法实例化bean
创建一个UserDao和它的实现类
UserDao
java
package com.csx.dao;
public interface UserDao {
public void say();
}
UserDaoImpl
java
package com.csx.dao.impl;
import com.csx.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void say() {
System.out.println("User实现类执行中...");
}
}
spring.xml
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="userDao" class="com.csx.dao.impl.UserDaoImpl"/>
</beans>
APP
java
package com.csx;
import com.csx.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class APP {
public static void main(String[] args) {
ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
userDao.say();
}
}
此时采用默认的无参构造来创建UserDaoImpl对象,交给IOC容器管理,如果此时没有无参构造,则创建失败。
创建一个属性,并创建一个构造,导致默认的无参构造失效,则程序运行失败。
注意: 构造方法可以写也可以不写(系统默认给无参构造方法),但是一旦写了构造方法,一定要书写无参的构造方法。
静态工厂实例化bean
使用工厂实例化bean(早期一些项目中使用,目的是为了解耦),即创造对象不直接new,而是通过工厂的方式获取对象
创建工厂类,
注意:工厂中实例化对象的方法是静态的。
UserStaticFactory
java
package com.csx.factory;
import com.csx.dao.UserDao;
import com.csx.dao.impl.UserDaoImpl;
public class UserStaticFactory {
public static UserDao getUserDao(){
return new UserDaoImpl();
}
}
工厂类的spring.xml的配置文件设置
spring.xml
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="userDao" class="com.csx.dao.impl.UserDaoImpl"/>-->
<bean id="userDao" class="com.csx.factory.UserStaticFactory" factory-method="getUserDao"/>
</beans>
id:工厂类的别名
class:配置工厂类的全限定名
factory-method:工厂类中的静态方法名
APP
java
public class APP {
public static void main(String[] args) {
ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
userDao.say();
}
}
实例工厂实例化bean
UserFactory
java
package com.csx.factory;
import com.csx.dao.UserDao;
import com.csx.dao.impl.UserDaoImpl;
public class UserFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
实例工厂中的方式是实例的,不是静态的,因此配置文件中的bean配置也有一些区别
spring.xml
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="userDao" class="com.csx.dao.impl.UserDaoImpl"/>-->
<!-- <bean id="userDao" class="com.csx.factory.UserStaticFactory" factory-method="getUserDao"/>-->
<bean id="userFactory" class="com.csx.factory.UserFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
</beans>
APP
java
public class APP {
public static void main(String[] args) {
ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
userDao.say();
}
}
实现FactoryBean接口的方式实例化
本质上是对实例工厂实例化bean的一种简化,我们可以看到:
因为实例工厂实例化bean的方式,需要创建一个工厂类对象,但这个对象只在实例化bean的时候使用一次,spring针对这个方式进行了改良。目的是为了简化配置。
UserFactoryBean
创建一个类实现FactoryBean接口,泛型为想要管理的接口类
java
public class UserFactoryBean implements FactoryBean<UserDao> {
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
}
spring.xml
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="userDao" class="com.csx.dao.impl.UserDaoImpl"/>-->
<!-- <bean id="userDao" class="com.csx.factory.UserStaticFactory" factory-method="getUserDao"/>-->
<!-- <bean id="userFactory" class="com.csx.factory.UserFactory"/>-->
<!-- <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>-->
<bean id="userDao" class="com.csx.factory.UserFactoryBean"/>
</beans>
此时spring.xml的配置可以直接管理工厂类
APP
java
public class APP {
public static void main(String[] args) {
ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
userDao.say();
}
}
总结
spring实例化bean的方式,实际上就是spring创建并管理java对象的方式,主要使用反射机制,调用无参构造方法实现。至于静态工厂和实例化工厂创建bean的方式,是为了兼容一些老的项目而采用的方式,目的是为了解耦。