一、Spring配置的一些小笔记
1、<bean>标签的属性:
<bean name="user" class="com.dunka.bean.User" lazy-init="true">
a) name 是一个名字,可以通过name到容器获取对象
name 可以使用特殊字符、可以重复,但是实际开发中并不推荐
其中 id和name 基本相同,但不能使用特殊字符亦不能重复
b)class 是被管理对象的全包名,spring根据全包名创建对象
c)延迟加载lazy-init true 就是创建容器时不加载配置的bean对象,在获取的时候才创建
***ApplicationContext配置的所有bean都会在容器创建的时候被创建出来,而且都是以空参构造方法为默认方法。
d)scope="singleton" 单例模式 容器只创建一个对象,每次向容器请求分配对象,都是同一个对象
scope="prototype"多例模式 容器在每次请求都会创建新的对象,所以每次getBean都是新的对象。
scope="request" 在web环境下,如果这个对象属性scope为request被创建出来,其生命周期会与request的一致,请求结束则die
scope="session"同理,与session的生命周期一致
e)init-method:初始化方法,在对象创建之后调用的初始化方法,单例、多例适用
f)destory-method:销毁方法,在容器关闭的使用,acontext.close(),之后调用这个方法。但有一点要注意的是,scope="prototype"时,对象由容器交由我们自己管理,所以在关闭容器的时候,并不会调用这个方法。
2、属性注入
a)SET方法
值属性注入
<bean name="user" class="com.dunka.bean.User">
<!-- 属性注入 SET方法 -->
<property name="u_id" value="1"/>
<property name="u_username" value="隔壁老杨"/>
<property name="u_password" value="123456"/>
</bean>
引用对象注入
public class User {
private Integer u_id;
private String u_username;
private String u_password;
private Pet u_pet;
}
public class Pet {
private String petType;
private String color;
}
<bean name="user" class="com.dunka.bean.User">
<!-- 属性注入 SET方法 -->
<property name="u_id" value="1"/>
<property name="u_username" value="隔壁老杨"/>
<property name="u_password" value="123456"/>
<!-- 属性注入 引用对象注入 -->
<property name="u_pet" ref="dog"/>
</bean>
<!-- 将Pet交由Spring容器管理 被引用对象-->
<bean name="dog" class="com.dunka.bean.Pet">
<property name="petType" value="柴犬"/>
<property name="color" value="黄色"/>
</bean>
b)构造方法注入
name是指构造方法中的相对应的参数名,value是值类型的注入、ref是引用对象类型的注入、type用于指定参数类型,index用于指定参数的位置(从0开始)
public User(String u_username, Pet u_pet) {
System.out.println("方法1 String ,Pet");
this.u_username = u_username;
this.u_pet = u_pet;
}
public User(Integer u_username, Pet u_pet) {
System.out.println("方法2 Integer ,Pet");
this.u_username = u_username.toString();
this.u_pet = u_pet;
}
public User(Pet u_pet,Integer u_username) {
System.out.println("方法3 Pet ,Integer");
this.u_username = u_username.toString();
this.u_pet = u_pet;
}
<bean name="user1" class="com.dunka.bean.User">
<constructor-arg name="u_username" value="666" type="java.lang.Integer"
index="0" />
<constructor-arg name="u_pet" ref="dog" index="1"/>
</bean>
c)复杂类型注入:array\list\set\map\properties
复杂类型实体类:
public class MyCollection {
//数组
private Object[] array;
//list
private List list;
//set
private Set set;
//map
private Map map;
//Properties
private Properties pro;
}
在applicationContext_injection.xml中加入的bean标签:可以注意到的是在每一种类型的赋值里,都可以用<ref bean="dog"/>引用之前的bean,以达到值复用的效果,无须重复赋值
<!-- 复杂类型注入 -->
<bean name="collection" class="com.dunka.bean.MyCollection">
<!-- array数组 -->
<property name="array" >
<array>
<value>123</value>
<value>abc</value>
<ref bean="dog"/>
</array>
</property>
<!-- list -->
<property name="list">
<list>
<value>456</value>
<value>jdj</value>
<ref bean="user1"/>
</list>
</property>
<!-- set -->
<property name="set">
<set>
<value>999</value>
<value>dunka</value>
<ref bean="dog"/>
</set>
</property>
<!-- map -->
<property name="map">
<map>
<entry key="username" value="dddd"/>
<entry key="password" value="123"/>
<entry key-ref="user1" value="dog"/>
</map>
</property>
<!-- properties -->
<property name="pro">
<props>
<prop key="name">老杨</prop>
<prop key="user1">dog</prop>
</props>
</property>
</bean>
测试类
@Test
public void test_injection1() {
ClassPathXmlApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext_injection.xml");
MyCollection mC = (MyCollection) aContext.getBean("collection");
System.out.println(mC);
}
由于没有使用过properties,所以我上网找了一篇文章专门说java.util.properties的,说的很详细,稍微明白这个类型是做什么的。如果以后会用到,便于回顾:https://www.cnblogs.com/bakari/p/3562244.html
二、注解配置
(1)将对象注册到容器
a)导入aop包,添加context的约束
并开启组件扫描,以下例子重点说明实体类的注解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-4.3.xsd">
<!-- 开启组件扫描 base-package 扫描该包以及其子包下的所有注解 -->
<context:component-scan base-package="com.dunka.bean"/>
</beans>
b)建立一个User2实体类
//<bean name="user" class="com.dunka.bean.User">
@Component("user")
//@Controller("user") //对应web层
//@Service("user") //对应Service层
//@Repository("user") //对应DAO层
//@Scope(scopeName="prototype")
public class User2 {
@Value(value="1")//在字段上使用此注解是暴力反射下的结果,不推荐
private Integer u_id;
private String u_username;
private String u_password;
private Pet u_pet;
public User2() {
System.out.println("User2空构造方法");
}
public Integer getU_id() {
return u_id;
}
public void setU_id(Integer u_id) {
this.u_id = u_id;
}
public String getU_username() {
return u_username;
}
@Value("Dunka") //直接在SET方法上注入
public void setU_username(String u_username) {
this.u_username = u_username;
}
public String getU_password() {
return u_password;
}
public void setU_password(String u_password) {
this.u_password = u_password;
}
public Pet getU_pet() {
return u_pet;
}
//自动装配,在容器中只有一个对象的时候适用
// @Autowired
//手动装配,容器中有多个同类型对象
@Resource(name="dog")
public void setU_pet(Pet u_et) {
this.u_pet = u_et;
}
@Override
public String toString() {
return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password + ", u_et=" + u_pet
+ "]";
}
//在构造方法后调用
@PostConstruct
public void userInit() {
System.out.println("userInit");
}
//在销毁之前调用
@PreDestroy
public void userDestory() {
System.out.println("userDestory");
}
}
这里解释一下各个注解:
(1)在XML文件中配置这个<bean name="user" class="com.dunka.bean.User">标签,相对应以下的@Component\@Controller\@Service\@Repository四个注解,在实际开发应用中比较少使用到@Component,其他三个标签使用在对应的层开发中,会更清晰并且易读懂
@Component("user")
@Controller("user") //对应web层
@Service("user") //对应Service层
@Repository("user") //对应DAO层
@Scope(scopeName="prototype")这个注解是对应<bean>中的scope属性,在没有注解的情况下默认是单例模式,可以通过注解中的属性更改创建对象的模式。
@PostConstruct 在构造方法后调用
@PreDestroy 在销毁之前调用
对于简单的属性注入:可在字段上、SET方法上使用
@Value(value="1")//在字段上使用此注解是暴力反射下的结果,不推荐
@Value("Dunka") //直接在SET方法上注入
对于对象的引用注入:
@Autowired 自动装配,在容器中只有一个对象的时候适用
@Resource(name="dog") 手动装配,容器中有多个同类型对象
c)测试类
@Test
public void test_injection1() {
ClassPathXmlApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext_annotation.xml");
User2 user2 = (User2) aContext.getBean("user");
User2 user3 = (User2) aContext.getBean("user");
System.out.println(user2 == user3);
aContext.close();
}
@Test
public void test_injection2() {
ClassPathXmlApplicationContext aContext = new ClassPathXmlApplicationContext("applicationContext_annotation.xml");
User2 user2 = (User2) aContext.getBean("user");
System.out.println(user2);
}
(2)Spring_JUnit框架整合
a)导入test包
利用之前的实体类,写一个测试
@RunWith(SpringJUnit4ClassRunner.class) //使用junit进行测试,帮助我们创建容器
@ContextConfiguration("classpath:applicationContext_injection.xml") //读取配置文件
public class test_SpringUnit {
@Resource(name = "dog")
private Pet pet;
@Test
public void test_injection() {
System.out.println(pet);
}
}
其中的注解说明:
@RunWith(SpringJUnit4ClassRunner.class) 使用junit进行测试,帮助我们创建spring容器
@ContextConfiguration("classpath:applicationContext_injection.xml") 读取配置文件
(3)分包配置问题:一个项目中可能会有很多配置文件,这时候需要有一个主配置文件,集中扫描该配置文件,将其他会引用到的配置文件导入其中,用到<import>标签
<!-- 导入其他配置文件 -->
<import resource="/applicationContext_injection.xml"/>
测试时:@ContextConfiguration中读取的是主配置文件的路径