一.Spring—Bean概述
Spring框架性质是属于容器性质的,容器中装什么对象就有什么功能,能帮其他框架管理对象.
Spring容器中的对象统称为Bean.
Bean体现了Spring如下特性
IOC控制反转:把控制对象生命周期的权利交给第三方(spring)管理
DI依赖注入:把Java程序中的对象创建的权利由第三方(spring)管理
二.Bean的创建
直接上代码,具体解释见代码注释
User.java
public class User {
@Override
public String toString() {
String str=super.toString()+"#username="+getUsername()+"#password="+getPassword();
return str;
}
private String username;
private String password;
public User() {
System.out.println("空参构造方法创建User");
}
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;
}
public void init(){
System.out.println("初始化方法");
}
public void destroy(){
System.out.println("销毁方法");
}
}
beancreate.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 必须导入约束文件 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User对象交给spring容器管理 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象. 可以重复.可以使用特殊字符.
id属性: 与name属性一模一样. 名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性. -->
<!-- 创建方式1:空参构造创建 -->
<bean name="userone" class="cjx.beanCreate.User" scope="singleton"></bean>
<!-- 创建方式2:静态工厂创建 调用UserFactory的createUser方法创建名为user2的对象.放入容器-->
<bean name="usertwo" class="cjx.beanCreate.BeanFactory" factory-method="createUser1"></bean>
<!-- 创建方式3:实例工厂创建 调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器-->
<bean name="userthree" factory-bean="UserFactory" factory-method="createUser2"></bean>
<bean name="UserFactory" class="cjx.beanCreate.BeanFactory" ></bean>
</beans>
beancreateone.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 创建方式1:空参构造创建 -->
<bean name="userone" class="cjx.beanCreate.User" scope="singleton"
init-method="init" destroy-method="destroy"></bean>
</beans>
beancreatetwo.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 创建方式2:静态工厂创建 调用UserFactory的createUser方法创建名为user2的对象.放入容器-->
<bean name="usertwo" class="cjx.beanCreate.BeanFactory" factory-method="createUser1"></bean>
</beans>
beancreatethree.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 创建方式3:实例工厂创建 调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器-->
<bean name="userthree" factory-bean="UserFactory" factory-method="createUser2"></bean>
<bean name="UserFactory" class="cjx.beanCreate.BeanFactory" ></bean>
<!-- 导入其他spring配置文件 -->
<import resource="beancreatetwo.xml"/>
</beans>
BeanCreate.java
public class BeanCreate {//bean的创建
/*spring有BeanFactory接口和ApplicationContext
* BeanFactory接口:原始接口,功能单一,每次获得对象时才创建对象
* ApplicationContext:每次容器启动时就会创建容器中配置的所有对象.并提供更多功能
* web开发中,使用applicationContext. 在资源匮乏的环境可以使用BeanFactory.
*/
//演示spring创建对象容器的方式 :/spring/src/cjx/bean/User.java
//spring在创建时会把配置文件里的对象全部创建
@Test
//创建方式1:空参构造创建
public void getbean1(){
//1 创建容器对象
//丛类路径下加载配置文件:ClassPathXmlApplicationContext("/cjx/bean/bean.xml")
//从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext("d:/xxx/yyy/xxx")
ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanCreate/beancreate.xml");
//2 向容器"要"user对象
User u = (User) ac.getBean("userone");
//3 打印user对象
System.out.println(u);
}
@Test
//创建方式2:静态工厂创建
public void getbean2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanCreate/beancreate.xml");
User u = (User) ac.getBean("usertwo");
System.out.println(u);
}
@Test
//创建方式2:动态工厂创建
public void getbean3(){
ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanCreate/beancreate.xml");
User u = (User) ac.getBean("userthree");
System.out.println(u);
}
}
/*scope属性:
* singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例
* prototype:多例对象.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.
* 整合struts2时,ActionBean必须配置为多例的.(struts2每次请求都会创建新的action)
* request:web环境下.对象与request生命周期一致.(不常用)
* session:web环境下,对象与session生命周期一致.(不常用)
*/
BeanCreateOne.java
public class BeanCreateOne {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("/cjx/beanCreate/beancreateone.xml");
User u = (User) ac.getBean("userone");
User u1 = (User) ac.getBean("userone");
User u2 = (User) ac.getBean("userone");
User u3 = (User) ac.getBean("userone");
System.out.println(u);
System.out.println(u1==u);
System.out.println(u1==u2);
System.out.println(u3==u2);
//测试初始化和销毁方法(需要在文件里配置,和类中提供方法)
ac.close();//用实现类(里面有close方法)
}
}
BeanCreateTwo.java
public class BeanCreateTwo {
public static void main(String[] args) {
@SuppressWarnings("resource")
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("/cjx/beanCreate/beancreatetwo.xml");
User u = (User) ac.getBean("usertwo");
System.out.println(u);
}
}
BeanCreateThree.java
public class BeanCreateThree {
public static void main(String[] args) {
@SuppressWarnings("resource")
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("/cjx/beanCreate/beancreatethree.xml");
User u = (User) ac.getBean("userthree");
System.out.println(u);
}
}
BeanFactory.java
public class BeanFactory {
@Test
public static User createUser1(){//静态工厂
System.out.println("静态工厂创建User");
return new User();
}
@Test
public User createUser2(){//实例(动态)工厂
System.out.println("实例(动态)工厂创建User");
return new User();
}
}
三.Bean的注入
直接上代码,具体解释见代码注释
User.java
public class User {
private String username;
private String password;
private Car car;
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", car=" + car + "]";
}
public User() {
System.out.println("无参构造!");
}
public User(String username, String password, Car car) {
System.out.println("有参构造!(String username, String password, Car car)");
this.username = username;
this.password = password;
this.car = car;
}
public User( Car car,String username, String password) {
System.out.println("有参构造!( Car car,String username, String password) ");
this.username = username;
this.password = password;
this.car = car;
}
public User(Integer username, String password, Car car) {
System.out.println("有参构造!(Integer username, String password, Car car)");
this.username = username+"";
this.password = password;
this.car = car;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
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;
}
}
Car.java
public class Car {
private String name;
private Integer age;
@Override
public String toString() {
return "Car [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Collection.java
public class Collection {
private Object[] arr;//数组类型注入
private List list;//List/set类型注入
private Map map;//map类型注入
private Properties prop;//Properties类型注入
@Override
public String toString() {
return "Collection [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", prop=" + prop + "]";
}
public Object[] getArr() {
return arr;
}
public void setArr(Object[] arr) {
this.arr = arr;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
}
beaninjection.xml
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- set方式注入: -->
<bean name="user1" class="cjx.beanInjection.User">
<!-- 值类型注入:为User对象注入值 -->
<property name="username" value="tom"></property>
<property name="password" value="123"></property>
<!-- 引用类型注入:为User对象注入下方的car对象 -->
<property name="car" ref="car"></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cjx.beanInjection.Car">
<property name="name" value="兰博基尼"></property>
<property name="age" value="11"></property>
</bean>
<!-- 构造函数注入:name="username" index="0" -->
<bean name="user2" class="cjx.beanInjection.User">
<constructor-arg name="username" value="jerry" index="0"></constructor-arg>
<constructor-arg name="password" value="456"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
<!-- 构造函数注入:name="username" index="1" -->
<bean name="user3" class="cjx.beanInjection.User">
<constructor-arg name="username" value="jerry" index="1"></constructor-arg>
<constructor-arg name="password" value="789"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
<!-- 构造函数注入:name="username" index="0" type="java.lang.Integer" -->
<!-- 构造函数注入 name:构造函数的参数名 index:构造函数的参数索引 type:构造函数的参数类型 -->
<bean name="user4" class="cjx.beanInjection.User">
<constructor-arg name="username" value="123456789"
index="0" type="java.lang.Integer"></constructor-arg>
<constructor-arg name="password" value="789"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
<!-- p名称空间注入 首先要导入约束xmlns:p="http://www.springframework.org/schema/p" -->
<bean name="user5" class="cjx.beanInjection.User" p:username="jack"
p:password="963" p:car-ref="car"></bean>
<!-- spel注入:spring expression language :spring表达式语言 不支持引用类型,只用于值类型。取其他对象的值。 -->
<bean name="user6" class="cjx.beanInjection.User">
<property name="username" value="#{user5.username}"></property>
<property name="password" value="#{user4.password}"></property>
<property name="car" ref="car"></property>
</bean>
<!-- 复杂类型注入 -->
<bean name="collection" class="cjx.beanInjection.Collection">
<!-- array注入 -->
<!-- 如果数组中只注入一个值,直接使用value或ref <property name="arr" value="tomcat"></property> -->
<!-- array注入:多元素 -->
<property name="arr">
<array>
<value>tom</value>
<value>jake</value>
<ref bean="user6" />
</array>
</property>
<!-- list注入:如果只注入一个值,直接使用value或ref -->
<property name="list">
<list>
<value>rose</value>
<value>taomcat</value>
<ref bean="user3" />
</list>
</property>
<!-- map注入 -->
<property name="map">
<map>
<entry key="url" value="www.baidu.com"></entry>
<entry key="car" value-ref="car"></entry>
<entry key-ref="user1" value-ref="user2"></entry>
</map>
</property>
<!-- Properties注入 -->
<property name="prop">
<props>
<prop key="driverclass">com.jdbc.mysql.driver</prop>
<prop key="username">cjx</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
</beans>
BeanInjection.java
public class BeanInjection {//bean的注入
@Test
public void getbean1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanInjection/beaninjection.xml");
User u = (User) ac.getBean("user6");
System.out.println(u);
}
@Test
public void getbean2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanInjection/beaninjection.xml");
Collection c = (Collection) ac.getBean("collection");
System.out.println(c);
}
}
四.Bean的注解
直接上代码,具体解释见代码注释
User.java
//import org.springframework.stereotype.Controller;
//import org.springframework.stereotype.Repository;
//import org.springframework.stereotype.Service;
@Component("user")// 标记为组件,并设置名称为user,放在类前
// @Service("user")// Service层注解
// @Controller("user")//Web层注解
// @Repository("user")//Dao层注解
//上面四个注解的功能相同,为了区分不同层的对象,提供了下面三个注解
@Scope(scopeName="singleton")//指定对象的作用域,默认是单例(singleton),可以设置为多例(prototype)
public class User {// 使用注解代替xml配置
@Value("tom")// 赋值,放在属性前,通过反射赋值,不走set方法,破坏了对象的封装性。
private String username;
private String password;
// @Autowired//根据类型自动装配,对象属性赋值,但如果匹配到多个类型一致的对象,将无法选择
// @Qualifier("car")//根据名称自动装配,对象属性赋值
//上面两个注解要一起使用,或只用第一个
@Resource(name="car")//手动注入,指定对象名称
private Car car;
@Value("123456789")// 赋值,放在set方法前,通过set方法赋值,推荐使用
public void setPassword(String password) {
System.out.println("setPassword");
this.password = password;
}
@PostConstruct//在对象创建后被调用,相当于init-method
public void init(){
System.out.println("初始化方法!");
}
@PreDestroy//在对象销毁之前被调用,相当于destory-method
public void destory(){
System.out.println("销毁方法!");
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", car=" + car + "]";
}
public String getPassword() {
return password;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
System.out.println("setUsername");
this.username = username;
}
}
Car.java
@Component("car")
public class Car {
@Value("兰博基尼")
private String name;
@Value("66")
private Integer age;
@Override
public String toString() {
return "Car [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
beanAnnotate.xml
<?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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
<!-- 使用注解代替xml配置
在/spring/src/cjx/beanCreate/beancreate.xml基础上
导入约束
···\spring-framework-4.2.4.RELEASE\schema\context\spring-context-4.2.xsd
-->
<!-- 导包:spring-aop-4.2.4.RELEASE.jar -->
<!-- 组件自动扫描:指定扫描指定包下所有类的注解,包括子包。 -->
<context:component-scan base-package="cjx.beanAnnotate"></context:component-scan>
</beans>
BeanAnnotateTest.java
//spring整合Junit的测试功能
//导包spring-test-4.2.4.RELEASE.jar
//创建容器
@RunWith(SpringJUnit4ClassRunner.class)
//指定配置文件,路径前面要加classpath:
@ContextConfiguration("classpath:cjx/beanAnnotate/beanAnnotate.xml")
public class BeanAnnotateTest {
//将user对象注入到u变量
@Resource(name="user")
private User u;
@Test
public void getbean(){
System.out.println(u);
}
}
BeanAnnotate.java
public class BeanAnnotate {
@Test
public void getbean() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("cjx/beanAnnotate/beanAnnotate.xml");
User u = (User) ac.getBean("user");
System.out.println(u);
ac.close();
}
}