Spring中的Bean

Posted 敲出一片天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中的Bean相关的知识,希望对你有一定的参考价值。

Bean的配置

  Spring如同一个工厂,用于生产和管理Spring容器中的Bean。使用这个工厂,需要开发者对Spring的配置文件进行配置。在实际开发中,最常采用XML格式的配置方式,即通过XML文件来注册并管理Bean之间的依赖关系。

Bean的作用域

  1. singleton
      singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean的id属性相匹配,就会返回同一个Bean的实例。singleton作用域对于无会话状态的Bean(如Dao组件、Service组件)来说,是最理想的选择。
<!-- scope作用域 单例(singleton)-->
		<bean id="scope" class="com.ssm.scope.Scope" scope="singleton"/>
  1. prototype
      对需要保持会话状态的Bean应用使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该Bean的请求都创建一个新的实例。
<!-- scope作用域 原型(prototype)-->
		<bean id="scope1" class="com.ssm.scope.Scope" scope="prototype"/>
  1. 测试
package com.ssm.scope;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ScopeTest {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new 
				ClassPathXmlApplicationContext("applicationContext.xml");
		
		// 如果是单例模式,则创建同一个实例
		System.out.println("singleton创建的对象:");
		System.out.println(applicationContext.getBean("scope"));
		System.out.println(applicationContext.getBean("scope"));
		// 如果是原型模式,则创建不同实例
		System.out.println("prototype创建的对象:");
		System.out.println(applicationContext.getBean("scope1"));
		System.out.println(applicationContext.getBean("scope1"));
	}
}	

Bean的三种装配方式

1.xml装配

  Spring提供了两种基于XML的装配方式:设值注入(Setter Injection)和构造注入(Constructor Injection)。下面就读讲解如何在XML配置文件中使用这两种注入方式来实现基于XML的装配。
在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求。

  • Bean类必须提供一个默认的无参构造方法。
  • Bean类必须为需要注入的属性提供对应的setter方法。

使用设值注入时,在Spring配置文件中,需要使用元素的子元素来为每个属性注入值;而使用构造注入时,在配置文件里,需要使用元素的子元素来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

package com.ssm.assemble;

import java.util.List;

public class User {
	private String username;
	private String password;
	private List<String> list;

	/**
	 * 构造注入,需要提供带所有参数的构造方法
	 */
	public User(String username, String password, List<String> list) {
		super();
		this.username = username;
		this.password = password;
		this.list = list;
	}

	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + ", list=" + list + "]";
	}

	/**
	 * 设值注入,提供空构造方法,为所有属性提供setter()方法
	 */
	public User() {
		super();
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setList(List<String> list) {
		this.list = list;
	}

}

<!-- 构造注入 -->
		<bean id="user1" class="com.ssm.assemble.User">
			<constructor-arg index="0" value="user1"></constructor-arg>
			<constructor-arg index="1" value="password1"></constructor-arg>
			<constructor-arg index="2">
				<list>
					<value>list1</value>
					<value>list2</value>
				</list>
			</constructor-arg>
		</bean>
		
		<!-- 设值注入 -->
		<bean id="user2" class="com.ssm.assemble.User">
			<property name="username" value="user2"></property>
			<property name="password" value="password2"></property>
			<property name="list">
				<list>
					<value>list1</value>
					<value>list2</value>
				</list>
			</property>
		</bean>
package com.ssm.assemble;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XmlAssembleTest {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new 
				ClassPathXmlApplicationContext("applicationContext.xml");
		
		System.out.println(applicationContext.getBean("user1"));
		System.out.println(applicationContext.getBean("user2"));
	}
}

2.注解装配

package com.ssm.annotation;

import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao {
	@Override
	public void save() {
		System.out.println("userDao.save()");

	}

}
package com.ssm.annotation;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

@Service("userService")
public class UserServiceImpl implements UserService {
	
	@Resource(name="userDao")
	private UserDao userDao;
	
//	public void setUserDao(UserDao userDao) {
//		this.userDao = userDao;
//	}

	@Override
	public void save() {
		this.userDao.save();
		System.out.println("userService.save()");
	}

}
package com.ssm.annotation;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;

@Controller("UserController")
public class UserController {
	@Resource(name="userService")
	private UserService userService;
	
	
	
//	public void setUserService(UserService userService) {
//		this.userService = userService;
//	}



	public void save(){
		userService.save();
		System.out.println("UserController.save()");
	}
}

<?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-4.3.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-4.3.xsd">
   
   <!-- 使用context命名空间,在配置文件中开启相应的注解处理器 -->
   <context:annotation-config />
   <!-- 分别定义3个Bean实例 -->
   <bean id="userDao" class="com.ssm.annotation.UserDaoImpl" />
   <bean id="userService" class="com.ssm.annotation.UserServiceImpl" />
   <bean id="UserController" class="com.ssm.annotation.UserController" />
   
   
   <!-- 也可以通过以下代码,实现扫描指定的包下的所有bean,从而替换掉上面的三行代码,还需引入spring aop 的jar包
   <context: component-scan base-package="com.ssm.annotation"/>
    -->
    
    
</beans>
package com.ssm.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnotationAssembleTest {
	private static ApplicationContext applicationContext;
	public static void main(String[] args) {
		applicationContext = new ClassPathXmlApplicationContext("com/ssm/annotation/annotation.xml");
		
		UserController userController = (UserController)applicationContext.getBean("UserController");
		userController.save();
	}
}

3.自动装配

  虽然使用注解的方式装配Bean,在一定程度上减少了配置文件中的代码量,但是也有企业项目中是没有使用注解方式开发的,那么有没有什么办法既可以减少代码量,又能够实现Bean的装配呢?答案是肯定的, Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动地注入到其他Bean的Property中。

<!-- 自动装配 -->
    <bean id="userDao" class="com.ssm.annotation.UserDaoImpl" />
    <bean id="userService" class="com.ssm.annotation.UserServiceImpl" autowire="byName"/>
    <bean id="UserController" class="com.ssm.annotation.UserController" autowire="byName"/>
    

以上是关于Spring中的Bean的主要内容,如果未能解决你的问题,请参考以下文章

[死磕 Spring 17/43] --- IOC 之从单例缓存中获取单例 bean

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

如何获取容器中的bean对象

Bean后置处理器 - BeanPostProcessor#postProcessAfterInitialization

BeanDefinitionRegistryPostProcessor自定义替换spring中的bean

BeanDefinitionRegistryPostProcessor自定义替换spring中的bean