使用XML方式装配Bean
1.实例化Bean的三种方式
- 使用构造方法实例化
在spring容器中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="demo1User" class="cn.spring.demo.User"></bean>
</beans>
测试
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("demo1User"); //相当于:User user = new User(); 直接创建实例
System.out.println(user);
}
- 使用静态工程方法实例化
在spring容器中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="demo2User" class="cn.spring.demo.Demo2BeanFactory" factory-method="getDemo2Bean"></bean>
</beans>
提供工厂类
public class Demo2BeanFactory {
public Demo2BeanFactory(){
System.out.println("demo2 不执行");
}
/**
* 必须提供 static方法
* @return
*/
public static User getDemo2Bean(){
return new User();
}
}
测试
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("demo2User");//相当于: User user = BeanFatory.getUserBean(); 通过工厂的静态方法获得需要的内容
System.out.println(user);
}
- 使用实例工厂方法
在Spring容器的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="demo3BeanFactory" class="cn.spring.demo.Demo3BeanFactory"></bean>
<bean id="demo3User" factory-bean="demo3BeanFactory" factory-method="getDemo2Bean"></bean>
</beans>
提供工厂类
public class Demo3BeanFactory {
public Demo3BeanFactory(){
//System.out.println("demo3 执行");
}
/**
* 非静态方法
* @return
*/
public User getDemo2Bean(){
return new User();
}
}
测试
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("demo3User");//相当于:BeanFactory factory = new BeanFactory();//先创建工厂 User user = factory.getUserBean();//在通过工厂的实例对象,执行非静态方法获得具体内容
System.out.println(user);
}
2.spring容器中bean元素id和name属性的区别
在spring容器中添加以下配置:
<bean id="helloService" class="cn.spring.demo.HelloService">
bean节点中Id和name的区别:
区别一:
id:指定唯一实例引用
name:可以指定多个实例引用,例如name=“名称1,名称2”
区别二:
id :id的命名要满足XML对ID属性命名规范
例如:必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号
name:如果Bean的名称中含有特殊字符,就需要使用name属性
例如:<bean name="# boy " class="cn.spring.demo.Boy"/>
因为name属性可以相同,所以后出现Bean会覆盖之前出现的同名的Bean
总结:项目开发的时候,强烈要求用id,因为id可以表示惟一引用。
3.Bean的作用域
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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 作用域
* singleton 单例,只创建一个实例。默认值
* prototype 多例,每一次都创建实例
* request,request范围,request.setAttribute
* session,session范围,session.setAttribute
* globalSession , prolet 分布式门户,sso(单点登录)将不同的应用的数据保存到globalSession中,达到数据共享
-->
<bean id="person" class="cn.spring.demo.Person" scope="prototype"></bean>
</beans>
4.Bean的生命周期
- 4.1生命周期详情
instantiate bean对象实例化
populate properties 封装属性
如果Bean实现BeanNameAware 执行 setBeanName
如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
如果Bean实现InitializingBean 执行 afterPropertiesSet
调用<bean init-method="init">
指定初始化方法 init
如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
执行业务处理
如果Bean实现 DisposableBean 执行 destroy
调用<bean destroy-method="customerDestroy">
指定销毁方法 customerDestroy
测试代码,实现类:
public class User implements BeanNameAware ,ApplicationContextAware,InitializingBean ,DisposableBean {
public User() {
System.out.println("1.构造方法执行");
}
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
System.out.println("2 装载属性,调用setter方法");
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public void setBeanName(String name) {
System.out.println("3.通过BeanNameAware接口,获得配置文件id属性的内容:" + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
System.out.println("4.通过ApplicationContextAware接口,获得Spring容器," + applicationContext);
}
/** 5 在后处理bean MyBeanPostProcessor.java 处 */
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("6.通过InitializingBean,确定属性设置完成之后执行");
}
public void userInit(){
System.out.println("7.配置init-method执行自定义初始化方法");
}
/** 8 在后处理bean MyBeanPostProcessor.java 处 */
@Override
public void destroy() throws Exception {
System.out.println("9.通过DisposableBean接口,不需要配置的销毁方法");
}
public void userDestroy(){
System.out.println("10.配置destroy-method执行自定义销毁方法");
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!--lifecycle 生命周期
1.构造方法执行
2 装载属性,调用setter方法
3.通过BeanNameAware接口,获得配置文件id属性的内容:lifeUser
4.通过ApplicationContextAware接口,获得Spring容器
5.实现BeanPostProcessor后处理,初始化前,执行postProcessBeforeInitialization方法
6.通过InitializingBean,确定属性设置完成之后执行
7.配置init-method执行自定义初始化方法
8.实现BeanPostProcessor后处理,在自定义初始化之后,执行postProcessAfterInitialization方法
//执行操作
9.通过DisposableBean接口,不需要配置的销毁方法
10.配置destroy-method执行自定义销毁方法
-->
<bean id="lifeUser" class="cn.spring.demo.User" init-method="userInit" destroy-method="userDestroy">
<property name="username" value="jack"></property>
<property name="password" value="1234"></property>
</bean>
<!-- 5.1配置 后处理bean -->
<bean class="cn.spring.demo.MyBeanPostProcessor"></bean>
</beans>
测试类
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("---->" + applicationContext);
User user = (User) applicationContext.getBean("lifeUser");
System.out.println(user); //业务执行
//必须手动执行关闭,才可以进行之后销毁的操作
applicationContext.close();
}
/**
* 后处理bean处理程序
* 需要注册给Spring容器,统一处理所有的bean,只需要注册
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if("lifeUser".equals(beanName)){
System.out.println("5. 实现BeanPostProcessor后处理Bean,初始化前 : " + beanName + ",bean实例: " + bean);
}
return bean; //返回当前bean,不做任何处理,可以生产代理类
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if("lifeUser".equals(beanName)){
System.out.println("8. 实现BeanPostProcessor后处理Bean,在自定义初始化之后 : " + beanName);
}
return bean;
}
}
5.依赖注入Bean属性
- 手动装配—构造方法
public class User {
private String username;
private int age;
private String password;
private int money;
public User(int money,String password) { //构造1
this.password = password;
this.money = money;
}
public User(String username, int age) { //构造2
this.username = username;
this.age = age;
}
@Override
public String toString() {
return "User [username=" + username + ", age=" + age + ", password="
+ password + ", money=" + money + "]";
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="injectConstructorUser" class="cn.spring.demo.User">
<constructor-arg index="0" value="1111"></constructor-arg>
<constructor-arg index="1" value="123456"></constructor-arg>
</bean>
</beans>
测试类
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("injectConstructorUser");
System.out.println(user); //业务执行
}
运行结果:User [username=null, age=0, password=123456, money=1111]
<bean id="injectConstructorUser" class="cn.spring.demo.User">
<constructor-arg index="0" value="1111" type="int"></constructor-arg>
<constructor-arg index="1" value="123456" type="java.lang.String"></constructor-arg>
</bean>
注意:在开发中为了指定执行的是那个构造方法,一般代用index属性和type属性结合的方式
- 手动装配—setter方法
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [userName=" + userName + ", password=" + password + "]";
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- setter方法 普通字段-->
<bean id="propertyInjectUser" class="cn.spring.demo.User">
<property name="userName" value="rose"></property>
<property name="password" value="5555"></property>
</bean>
</beans>
测试类
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("propertyInjectUser");
System.out.println(user); //业务执行
}
- 手动装配—接口注入
将已有的方法增强,如何将一个prototype(多例) bean注入给singleton(单例) Bean
public class UserService {
private Dao dao = new UserMySqlDao();
public Dao getDao() {
return dao;
}
public void find(){
getDao().find();
}
}
public interface Dao {
public void find();
}
public class UserMySqlDao implements Dao {
public void find(){
System.out.println("mysql 查询");
}
}
public class UserOracleDao implements Dao{
public void find(){
System.out.println("oracle 查询");
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- 不修改UserService原有代码的前提下,扩展service -->
<bean id="methodUserService" class="cn.spring.demo.UserService">
<lookup-method name="getDao" bean="methodOracleDao"/>
</bean>
<bean id="methodOracleDao" class="cn.spring.demo.UserOracleDao"></bean>
</beans>
测试
public class TestService {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("methodUserService");
userService.find();
}
}
- 手动装配—p命名空间
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [userName=" + userName + ", password=" + password + "]";
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- p命名空间 -->
<bean id="pInjectUser" class="cn.spring.demo.User" p:userName="tom" p:password="9999"></bean>
</beans>
- 手动装配—集合属性
List/Array集合
public class User {
private List<String> loves;
private String[] interest;
public List<String> getLoves() {
return loves;
}
public void setLoves(List<String> loves) {
this.loves = loves;
}
@Override
public String toString() {
return "User [loves=" + loves + "]";
}
public String[] getInterest() {
return interest;
}
public void setInterest(String[] interest) {
this.interest = interest;
}
}
Spring 容器
<?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="user" class="cn.spring.demo.User">
<property name="loves">
<list>
<value>小龙女</value>
<value>凤儿</value>
</list>
</property>
<property name="interest">
<array>
<value>葵花</value>
<value>菊花</value>
</array>
</property>
</bean>
</beans>
测试
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getLoves());
System.out.println(Arrays.toString(user.getInterest()));
}
}
结果:[小龙女, 凤儿],[葵花, 菊花]
Set集合
public class User {
private Set<String> loves;
public Set<String> getLoves() {
return loves;
}
public void setLoves(Set<String> loves) {
this.loves = loves;
}
}
Spring容器
<?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="user" class="cn.spring.demo.User">
<property name="loves">
<set>
<value>小龙女</value>
<value>凤儿</value>
</set>
</property>
</bean>
</beans>
测试
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getLoves());
}
}
运行结果:[小龙女, 凤儿]
Map集合
public class Book {
}
public class User {
private Map<String,Book> data;
public Map<String, Book> getData() {
return data;
}
public void setData(Map<String, Book> data) {
this.data = data;
}
}
Spring 容器
<?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="bookId" class="cn.spring.demo.Book"></bean>
<bean id="user" class="cn.spring.demo.User">
<property name="data">
<map>
<!-- 第一种写法 -->
<entry key="b001" value-ref="bookId">
</entry>
<!-- 第二种写法 -->
<entry>
<key >
<value>b002</value>
</key>
<ref bean="bookId"/>
</entry>
</map>
</property>
</bean>
</beans>
测试
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getData());
}
}
结果:{b001=cn.spring.demo.Book@15e7bc4, b002=cn.spring.demo.Book@15e7bc4}
Properties对象
public class User {
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
Spring容器
<?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="user" class="cn.spring.demo.User">
<property name="properties">
<props>
<prop key="1">男</prop>
<prop key="2">女</prop>
</props>
</property>
</bean>
</beans>
测试
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getProperties());
}
}
结果:{2=女, 1=男}
使用注解方式装配Bean
测试类
public class App {
public static void main(String[] args) {
/* @Component 衍生了以下三个注解,用于标识不同的层次
* @Controller 用于配置表示层web
* @Service 用于配置业务逻辑层service
* @Repository 用于配置数据访问层dao
*/
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
Web web = (Web)context.getBean("myweb");
web.save();
}
}
Web层
@Controller("myweb")
public class Web {
@Autowired
private Service service;
public void save(){
service.save();
System.out.println("web save");
}
}
Service层
@Service
public class Service {
@Autowired
@Qualifier("myDao")
private Dao dao;
public void save(){
dao.save();
System.out.println("service save");
}
}
Dao层
@Repository("myDao")
public class Dao {
public void save(){
System.out.println("dao save");
}
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 确定使用注解 -->
<context:annotation-config></context:annotation-config>
<!-- 自动扫描指定的包 -->
<context:component-scan base-package="cn.spring.demo"></context:component-scan>
</beans>
结果:
dao save
service save
web save
Bean初始化和销毁
public class App {
public static void main(String[] args) {
/*
* @PostConstruct
* public void init(){ 等价于 init-method="init"
*
* @PreDestroy
* public void destory(){ 等价于 destroy-method="destory"
*/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
Book book = (Book)context.getBean("book");
context.close();
}
}
@Component("book")
public class Book {
@PostConstruct
public void init(){
System.out.println("初始化");
}
@PreDestroy
public void destory(){
System.out.println("销毁");
}
}
Spring 容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 确定使用注解 -->
<context:annotation-config></context:annotation-config>
<!-- 自动扫描指定的包 -->
<context:component-scan base-package="cn.spring.demo"></context:component-scan>
<!-- xml配置
<bean id="book" class="cn.spring.demo.Book"
init-method="init" destroy-method="destory">
</bean>
-->
</beans>
Bean作用范围
public class App {
public static void main(String[] args) {
/*
* @Scope("singleton") 给当前bean配置范围,取值:singleton、prototype等
*/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/beans.xml");
Book book = (Book)context.getBean("book");
System.out.println(book);
Book book2 = (Book)context.getBean("book");
System.out.println(book2);
context.close();
}
}
Bean对象
@Component("book")
@Scope("singleton")
public class Book {
}
Spring容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 确定使用注解 -->
<context:annotation-config></context:annotation-config>
<!-- 自动扫描指定的包 -->
<context:component-scan base-package="cn.spring.demo"></context:component-scan>
</beans>
结果:
@Scope("singleton")
cn.spring.demo.Book@f8fae4
cn.spring.demo.Book@f8fae4
@Scope("prototype")
cn.spring.demo.Book@f8fae4
cn.spring.demo.Book@1fc493