文章目录
- 1. Bean的创建
- 1.1 构造器注入
- 1.2 不同类型的属性的set注入方式
- 1.3 扩展方式注入
- 1.4 XML文件中的其他配置属性
- 2. Bean的作用域
- 2.1 单例模式
- 2.2 原型模式
- 3. Bean的自动装配
- 3.1 XML中显示配置
- 3.2 Java代码中使用注解配置
- 4. 使用全注解的方式实现类的配置
1. Bean的创建
- SpringBean的创建主要实现理念是控制反转
- SpringBean的创建主要实现方式是依赖注入
- 依赖:Bean对象的创建依赖于容器
- 注入:Bean对象的所有属性由容器来注入
依赖注入一共有三种方式
- 构造器注入
- Set方法注入
- 扩展方式
1.1 构造器注入
- 使用无参构造方法创建对象(默认是实现方式)
- 使用有参构造时,在XML文件中传入参数,有3种方式
<!--
使用参数下标匹配:index代表参数下标,从0开始
使用参数类型匹配:type代表参数类型,基本类型直接使用,引用必须是全部限定类名
使用参数名:name代表构造函数中的参数名称
-->
<bean id="user" class="com.hust.pojo.User">
<constructor-arg index="0" value="123"/>
<constructor-arg type="java.lang.String" value="123"/>
<constructor-arg name="name" value="123"/>
</bean>
在配置文件加载的时候,容器所管理的对象已经全部初始化了
1.2 不同类型的属性的set注入方式
- 创建测试对象
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private Properties info; //配置类型
private String wife; //测试空指针
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.toString() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", info=" + info +
", wife='" + wife + '\'' +
'}';
}
}
- 不同类型属性值注入方式(applicationContext.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="address" class="com.hust.pojo.Address">
<property name="address" value="HUST"/>
</bean>
<bean id="student" class="com.hust.pojo.Student">
<!--普通值注入,使用value赋值-->
<property name="name" value="张三"/>
<!--引用注入/Bean注入-->
<property name="address" ref="address"/>
<!--数组注入-->
<property name="books">
<array>
<value>Java</value>
<value>Python</value>
<value>C++</value>
</array>
</property>
<!--List集合注入-->
<property name="hobbys">
<list>
<value>唱</value>
<value>跳</value>
<value>Rap</value>
<value>篮球</value>
</list>
</property>
<!--Map注入-->
<property name="score">
<map>
<entry key="语文" value="95"/>
<entry key="数学" value="98"/>
<entry key="英语" value="97"/>
</map>
</property>
<!--Set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>FIFA</value>
<value>NBA2K</value>
</set>
</property>
<!--null值注入-->
<property name="wife">
<null />
</property>
<!--Properties注入,结构类似于Map,注入方式不一样-->
<property name="info">
<props>
<prop key="学号">M202012123</prop>
<prop key="班级">M2003班</prop>
</props>
</property>
</bean>
</beans>
- 测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//在getBean后面添加类的类型,可以不用强转
Student student = context.getBean("student", Student.class);
System.out.println(student);
}
}
1.3 扩展方式注入
- 分为
p命名空间
和c命名空间
两种方式,分别需要导入XML约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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="user1" class="com.hust.pojo.Student" p:name="LoveLin"/>
<!--c命名空间方式,类中必须要有有参构造函数,否则会报错-->
<bean id="user2" class="com.hust.pojo.Student" c:name="Melo"/>
>
1.4 XML文件中的其他配置属性
- 别名,在使用
getBeans()
时可以使用别名代替
-
alias
:区分大小写,写在bean标签的外面,一对一的关系 -
name
:写在bean标签里面,可以同时取多个别名(使用逗号,空格,分号分割都可以)
<alias name="mySQLImpl" alias="impl1"/>
<bean id="mySQLImpl" class="com.hust.dao.UserDaoMySQLImpl" name="impl1,im1;i1 1"/>
- 单例,使整个系统中只有一个实例
<bean id="mySQLImpl" class="com.hust.dao.UserDaoMySQLImpl" scope="singleton"/>
-
import
,一般用于团队开发,可以将多个配置文件导入合并为一个
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
2. Bean的作用域
- 在bean标签中添加
scope
属性可以指定作用域,默认为单例模式 -
request
,session
,application
只能在web开发中使用
2.1 单例模式
- 默认即为单例模式,可以不写
<bean id="address" class="com.hust.pojo.Address" scope="singleton"/>
2.2 原型模式
- 每次使用
getBean()
都会产生一个新的对象
<bean id="address" class="com.hust.pojo.Address" scope="prototype">
3. Bean的自动装配
Spring满足Bean依赖的一种方式,Spring会在上下文中自动寻找并自动装配,有3种装配的方式
- 在XML中显示配置
- 在Java中显示配置
- 隐式自动装配
3.1 XML中显示配置
- 在bean标签里面有一个
autowire
属性;可以不用再在里面配置相关属性 -
byName
:根据名称自动装配;类中属性名必须与配置文件中bean的id要一致,setDog==dog
,需要bean的id唯一
<bean id="cat" class="com.hust.pojo.Cat"/>
<bean id="dog" class="com.hust.pojo.Dog"/>
<bean id="people" class="com.hust.pojo.People" autowire="byName">
<property name="name" value="张三" />
<!--<property name="cat" ref="cat" />
<property name="dog" ref="dog" />-->
</bean>
-
byType
:根据属性的类型来装配,会自动寻找对应的类型,类中的id可以省略,但有多个相同类型时会报错
<bean class="com.hust.pojo.Cat"/>
<bean class="com.hust.pojo.Dog"/>
<bean id="people" class="com.hust.pojo.People" autowire="byType">
<property name="name" value="张三" />
</bean>
3.2 Java代码中使用注解配置
-
JDK1.5
、Spring2.5
开始支持注解 - 大部分情况下都会使用注解的方式来进行配置,更方便快捷,需要在XML文件中添加支持(beans导入约束,context添加支持)
<?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/>
<!--配置文件中只需要添加id和class属性-->
<bean id="cat" class="com.hust.pojo.Cat"/>
<bean id="dog" class="com.hust.pojo.Dog"/>
<bean id="people" class="com.hust.pojo.People"/>
</beans>
- 在需要自动导入的地方添加
@Autowired
注解
public class People {
private String name;
@Autowired
private Cat cat;
@Autowired
private Dog dog;
...
//这种方式下可以不写对应属性的set方法
}
-
@Autowired
注解里面有一个required
属性,默认为true
,如果设置为false
,则说明这个属性可以为null
,否则不能为空
@Autowired(required = false)
private Dog dog;
- 如果
@Autowired
自动装配的环境比较复杂,自动装配无法通过一个注解完成,则我们可以使用@Qualifiler(value="xxx")
来指定唯一的注入对象
<!--此时自动装配无法自动识别装配对象-->
<!--如果里面有一个就是cat,则还是会运行成功,因为注解是根据byName来进行装配的-->
<bean id="cat1" class="com.hust.pojo.Cat"/>
<bean id="cat2" class="com.hust.pojo.Cat"/>
<bean id="dog1" class="com.hust.pojo.Dog"/>
<bean id="dog2" class="com.hust.pojo.Dog"/>
<bean id="people" class="com.hust.pojo.People"/>
@Autowired
@Qualifier(value = "cat1")
private Cat cat;
- 此外,也可以使用
@Resoure(name="xxx")
来进行指定
@Resource(name="dog2")
private Dog dog
@Resource
和@Autowired
的区别:
- 都是用于自动装配的,都可以放在属性的字段上面
@Autowired
自动通过byName
的方式实现装配;是Spring中的注解@Resource
先通过byName
装配,如果不匹配则通过byType
,是Java中的注解
4. 使用全注解的方式实现类的配置
- 编写需要装配的类,需要被扫描到
//说明这个类被Spring管理
@Component
public class User {
private String name;
public String getName() {
return name;
}
//注入属性值
@Value("aaa")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
- 需要创建config类
//这是一个配置类,类似于xml文件,也会被Spring管理,本质也是一个@Component
@Configuration
//要扫描的包
@ComponentScan("com.hust.pojo")
public class MyConfig {
//注册一个bean,相当于xml中的一个bean标签
@Bean
//这个方法的名字就相当于bean标签中的id属性
//这个方法的返回值就相当于bean标签中的class属性
public User getUser(){
//返回要注入的bean对象
return new User();
}
}
- 使用config获取context
public class MyTest {
public static void main(String[] args) {
//完全使用配置类的方式去获取context的方法
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
System.out.println(context.getBean("getUser", User.class).getName());
}
}