搜索
首页
笔记
案例
关于
课程列表
Spring
IOC
入门---新建Spring工程
容器接口与实现类
Bean管理(基于XML)
Bean管理(基于注解)
完全注解开发
AOP
AOP概述
AspectJ实现AOP
AOP的实现步骤---前置通知
其他通知的AOP实现
Spring集成Mybatis
Spring整合Mybatis
Spring事务
Spring事务管理
Spring中使用事务
Spring与Web
在Servlet中使用Spring框架
Spring5新功能
课程导航
计算机基础知识
C
Linux
linux常用软件
计算机网络
程序员修养
设计模式
工具
Git
composer
vim
IntelliJ IDEA
wireshark
laravel
Spring
SpringMVC
Maven
数据库
MySQL
Redis
MongoDB
JDBC
Mybatis
MyBatis-Plus
服务端编程
PHP
Java
shell script
JavaWeb
HTML / CSS
HTML
CSS
HTML5
CSS3
BOOTSTRAP
JavaScript
JavaScript
JQuery
layui
容器接口与实现类
Bean管理(基于注解)
Bean管理(基于XML)
Bean管理即两个操作:Spring创建对象、spring注入属性 有两种方法实现Bean管理:基于xml配置文件、基于注解以及完全注解方式。下面来介绍xml方式管理Bean。 ## 创建对象 ```xml
``` * id 属性:唯一标识 * class 属性:类全路径(包类路径) ```java String config = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(config); DemoService service = (DemoService) ac.getBean("demoService"); service.run(); ``` 创建对象时,默认使用无参构造器。 ## FactoryBean 很多java开发者在使用Spring框架中都见过后缀为FactoryBean的类,比如Mybatis-Spring中的SqlSessionFactoryBean。说到这里就不得不提BeanFactory。FactoryBean和BeanFactory特别容易让人混淆,面试还经常问到这两种概念。其实它们的作用和使用场景是不一样的。 BeanFactory用于访问Spring bean容器的根接口。原来我们更常用的ApplicationContext就是一个BeanFactory。我们通过bean的名称或者类型都可以从BeanFactory来获取bean。 FactoryBean是一个接口,定义如下: ```java public interface FactoryBean
{ String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"; @Nullable T getObject() throws Exception; @Nullable Class> getObjectType(); default boolean isSingleton() { return true; } } ``` - T getObject() 获取泛型T的实例。用来创建Bean。 - Class> getObjectType() 获取 T getObject()中的返回值 T 的具体类型。这里强烈建议如果T是一个接口,返回其具体实现类的类型。 - default boolean isSingleton() 用来规定 Factory创建的的bean是否是单例。这里通过默认方法定义为单例。 下面来演示如何使用FactoryBean - 实现接口 ```java public class FruitFactoryBean implements FactoryBean { private String name; public Object getObject() throws Exception { return new Fruit(name); } public Class> getObjectType() { return Fruit.class; } public boolean isSingleton() { return true; } public void setName(String name) { this.name = name; } } ``` - 配置FactoryBean ```xml
``` - 测试 ```java ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Object banana = applicationContext.getBean("banana"); Object apple = applicationContext.getBean("apple"); System.out.println(banana.getClass()); // class com.annotation.bean.Fruit System.out.println(apple.getClass()); // class com.annotation.bean.Fruit ``` 通过id名获取的bean对象的类型并不是FruitFactoryBean,而是getObjectType方法指定的返回类型。如果我们想要获取FruitFactoryBean,只需要在方法明前加上&即可。 ```java ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Object banana = applicationContext.getBean("&banana"); Object apple = applicationContext.getBean("apple"); System.out.println(banana.getClass()); // class com.annotation.factory.FruitFactoryBean System.out.println(apple.getClass()); // class com.annotation.bean.Fruit ``` ## Bean生命周期 生命周期:从对象创建到对象销毁的过程。 bean 生命周期 (1)通过构造器创建 bean 实例(无参数构造) (2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法) (3)调用 bean 的初始化的方法(**需要进行配置初始化的方法**) (4)bean 可以使用了(对象获取到了) (5)当容器关闭时候,调用 bean 的销毁的方法(**需要进行配置销毁的方法**) ```xml
public class Orders { //无参数构造 public Orders() { System.out.println("第一步 执行无参数构造创建 bean 实例"); } private String oname; public void setOname(String oname) { this.oname = oname; System.out.println("第二步 调用 set 方法设置属性值"); } //创建执行的初始化的方法 public void initMethod() { System.out.println("第三步 执行初始化的方法"); } //创建执行的销毁的方法 public void destroyMethod() { System.out.println("第五步 执行销毁的方法"); } } ``` **注:如果是多实例Bean,Spring容器不会帮我们销毁,需我们自行销毁** ## Bean作用域(scope/lazy) 我们可以通过 spring 配置文件 bean 标签里面属性(scope)来设置单实例还是多实例。 - singleton,表示是单实例对象(默认值) - prototype,表示是多实例对象 ```xml
``` singleton 和 prototype 区别: - singleton 单实例,prototype 多实例 - 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象。 设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建对象,在调用getBean 方法时候创建多实例对象(懒加载)。 那么,假如我想要单例,也想要懒加载,可是么? 答案是可以,设置属性lazy-init="true"即可,该属性默认值为false。 ```xml
``` ## 注入简单类型属性 bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。 根据注入方式的不同,常用的有两类:set方法注入、构造器注入。 ### 使用set方法注入(掌握) (1)创建一个类,定义属性和对应的set方法 ```java public class User { private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } 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; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } } ``` (2)在 spring 配置文件配置对象创建,配置属性注入 ```xml
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = ac.getBean("user", User.class); System.out.println(user); // User{name='James', age=36} ``` ### 构造器方法注入(理解) ``` public class Country { private String name; public Country(String name) { this.name = name; } @Override public String toString() { return "Country{" + "name='" + name + '\'' + '}'; } }
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); Country country = ac.getBean("country", Country.class); System.out.println(country); // Country{name='China'} ``` ## 注入其他类型属性 ### 空值及特殊值 (1)null 值 ```xml
``` (2)属性值包含特殊符号 ```xml
>]]>
``` ### 注入引用类型属性 #### 外部Bean(掌握) ```java package com.studyspring.bean; public class User { private String name; private int age; private Country country; public User() { } public void setName(String name) { this.name = name; } public void setCountry(Country country) { this.country = country; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", country=" + country + '}'; } } ``` 上述User类的Country属性,是一个引用类型。 ```xml
……
``` #### 内部Bean(了解) ```xml
``` ### 注入集合类型的属性 ```java public class Stu { //1 数组类型属性 private String[] courses; //2 list 集合类型属性 private List
list; //3 map 集合类型属性 private Map
maps; //4 set 集合类型属性 private Set
sets; public void setSets(Set
sets) { this.sets = sets; } public void setCourses(String[] courses) { this.courses = courses; } public void setList(List
list) { this.list = list; } public void setMaps(Map
maps) { this.maps = maps; } @Override public String toString() { return "Stu{" + "courses=" + Arrays.toString(courses) + ", list=" + list + ", maps=" + maps + ", sets=" + sets + '}'; } }
java 课程
数据库课程
张三
小三
MySQL
Redis
``` ## 引用类型属性自动注入 对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为`
`标签设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属性)。根据自动注入判断标准的不同,可以分为两种: - byName:根据名称自动注入 - byType: 根据类型自动注入 ### byName 方式自动注入 当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。 ![img](http://img.1024phper.com/blog21040211343374736) ### byType方式自动注入 使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了。 ![img](http://img.1024phper.com/blog21040211365147279) ## 为应用指定多个Spring配置文件 在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring 配置文件分解成多个配置文件。 多个配置文件中有一个总文件,总配置文件将各其它子文件通过`
`引入。在 Java代码中只需要使用总配置文件对容器进行初始化即可。 **aplicationContext.xml** ```xml
``` **bean_user.xml** ```xml
``` **bean_country.xml** ```xml
``` 也可使用通配符`*`。但此时要求主配置文件名不能满足*所能匹配的格式,否则将出现循环递归包含。 ```xml
```
容器接口与实现类
Bean管理(基于注解)
文章目录