Java Bean 规范
JavaBean:符合一定规范的Java对象,JavaBean规范不是语法规范,违反不会有编译错误。
- 需要定义包package。
- 有无参数构造器
- 需要实现序列化接口
- 包含使用 getXxx setXxx 声明的“Bean属性” xxx
- Bean属性(Bean Property)就是指 setXxx getXxx 方法
- 对象属性(Object Field)是指对象的实例变量。
例子:
class Person{ private String name="范传奇"; //实例变量,对象属性 String getName(){ //Bean属性 name return name; } void setName(String name){ //Bean属性 name this.name = name; } String getLastName(){ //Bean属性 lastName return name.substring(0,1); } }
例子:
Spring Hello World!
- 导入Spring IOC 组件包
- 创建被Spring IOC管理的对象组件 类
- 创建配置文件:通知Spring管理哪个对象组件
- 创建应用程序
- 创建Spring容器,读取Spring配置文件
- 从Spring容器中获取,被Spring管理的对象(控制反转)
- 调用对象的方法(验证)输出HelloWorld!
1.使用Junit测试更方便 导入Spring和JUnit包:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.9.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
2.创建 Java Bean类:
public class Demo { public void test() { System.out.println("Hello World!"); } }
3.编写配置文件 applicationContext.xml, 保存到resource文件夹
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- class 用于通知Spring,Spring会读取class属性的值 在Spring内部利用反射创建对象 id用于标识识别对象,id属性不能重复! --> <bean id="demo" class="day01.Demo"></bean> </beans>
4.编写测试类:
public class TestCase { ClassPathXmlApplicationContext ctx; //实例变量 @Before // init() 会在测试案例之前执行 //一般用于初始化测试案例的环境,如:初始化Spring容器 public void init() { ctx=new ClassPathXmlApplicationContext( "applicationContext.xml"); } @After // destroy 销毁,在测试案例执行以后执行 //用于回收系统资源。 public void destroy() { ctx.close(); } @Test public void testDemo() { /** * Spring Hello World! */ Demo demo = (Demo)ctx.getBean("demo"); demo.test(); } }
Spring支持对象别名
在Spring配置文件中可以为Java Bean对象定义别名,别名与ID功能一样:
<!-- alias: 别名,曾用名 --> <alias name="demo" alias="demo1"/>
测试
@Test public void testAlias(){ /* * 测试 在Spring中为 Java Bean对象声明别名 */ Demo demo = (Demo) ctx.getBean("demo1"); demo.test(); }
bean标签的id和name属性功能一样
配置文件:
<!-- bean 标签上的 id 属性和name属性功能一样 大多数使用 id 属性!id属性值不能重复 --> <bean name="demo2" class="day01.Demo"></bean>
重载的getBean方法
Spring 容器提供了 重载的getBean方法, 可以自动完成类型转换,不用写强制转型
@Test public void testGetBean() { /* * Spring 容器提供了 重载的getBean方法, * 可以自动完成类型转换,不用写强制转型 */ // 第一个参数是 Bean 的ID,第二个参数Bean对象的类型 Demo demo = ctx.getBean("demo", Demo.class); demo.test(); }
Spring Bean对象作用域(Scope)
- Spring 容器默认情况下按照“单例”管理对象。
- 单例:在软件中对象是唯一的一个实例现象
- 多次调用getBean获得的是同一个的对象的引用
- Spring使用bean标签的scope属性可以指定多例
- Spring默认情况下单例方式可以提高性能。
单例案例:
@Test public void testSingleton() { /* * 默认情况下 Spring 按照单例规则管理对象 * 使用同一个ID多次调用 getBean获得的引用是 * 同一个对象的引用。 */ Demo d1 = ctx.getBean("demo", Demo.class); Demo d2 = ctx.getBean("demo", Demo.class); System.out.println(d1==d2); //true }
多例案例配置:
<!-- scope 属性声明“原型prototype”创建多个实例 每次调用getBean时候都会创建一个新实例 --> <bean id="myBean" class="day01.Demo" scope="prototype"/>
测试:
@Test public void testPrototype() { /* * 使用scope="prototype"创建多个对象实例 * 每次调用getBean方法都会创建一个对象实例 */ Demo d1 = ctx.getBean("myBean", Demo.class); Demo d2 = ctx.getBean("myBean", Demo.class); System.out.println(d1==d2); }
bean 对象生命周期管理方法
- init-method 用于设定 初始化方法,创建对象以后立即执行
- destroy-method 用于设定 销毁方法,关闭容器销毁对象时候执行
- 仅对单例对象有效,多例对象上设置无效。
单例对象生命周期管理案例:
-
创建Bean类型
配置:
测试:
自动注入
- autowire="byName" 根据名字自动注入:根据对象的Bean属性名查找匹配Bean的ID,如果名字一致, 则自动注入Bean属性。 如果注入的对象类型不兼容,则失败。
- autowire="byType" 根据类型自动注入:根据对象的Bean属性类型查找匹配Bean的类型,如果类型兼容, 则自动注入Bean属性。 如果注入的对象类型不唯一,则出错误。
配置:
<!-- 测试按名字自动注入 --> <bean id="worker" class="day02.Worker" autowire="byName"></bean> <bean id="tool" class="day02.Saw"></bean>
Bean属性参数注入
Spring 支持各种类型参数注入:
-
编写测试类
public class DemoBean { private int num; private double price; private boolean test; private String name; //List集合 private List<String> city; //数组 private String[] arr; //Set集合 private Set<String> names; //对象集合 private List<Tool> tools; /* * Spring 支持基本类型Bean属性注入 */ public int getNum() { return num; } public void setNum(int num) { this.num = num; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public boolean isTest() { return test; } public void setTest(boolean test) { this.test = test; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getCity() { return city; } public void setCity(List<String> city) { this.city = city; } public String[] getArr() { return arr; } public void setArr(String[] arr) { this.arr = arr; } public Set<String> getNames() { return names; } public void setNames(Set<String> names) { this.names = names; } public List<Tool> getTools() { return tools; } public void setTools(List<Tool> tools) { this.tools = tools; } @Override public String toString() { return "DemoBean [num=" + num + ", price=" + price + ", test=" + test + ", name=" + name + ", city=" + city + ", arr=" + Arrays.toString(arr) + ", names=" + names + ", tools=" + tools + "]"; } }
配置:
<!-- Spring 可以为Bean对象注入各种类型的"Bean属性" --> <bean id="demoBean" class="day02.DemoBean"> <!-- 使用vaule属性注入基本值(基本类型和字符串) --> <property name="num" value="58"/> <property name="price" value="88.8"/> <property name="name" value="Tom"/> <property name="test" value="true"/> <!-- 使用 array 子元素注入数组 --> <property name="arr"> <array> <value>黄</value> <value>品</value> <value>青</value> <value>黑</value> </array> </property> <!-- list子元素注入集合 --> <property name="city"> <list> <value>魔都</value> <value>帝都</value> <null></null> <!-- 注入 null 值 --> </list> </property> <!-- set子元素注入set集合 --> <property name="names"> <set> <value>熊大</value> <value>熊二</value> </set> </property> <!-- 注入对象集合, list 元素和 bean 元素配合实现--> <property name="tools"> <list> <bean class="day02.Axe"></bean> <bean class="day02.Saw"></bean> <!-- ref 用于引用Spring容器中的Bean对象 --> <ref bean="axe"/> </list> </property> </bean>
测试:
@Test public void testBeanProperty() { /* * Spring 可以为Bean对象注入各种类型的"Bean属性" * DI 功能很强大! */ DemoBean bean=ctx.getBean("demoBean", DemoBean.class); System.out.println(bean); }
利用Spring 管理数据库连接池
利用Spring的ICO和DI功能,管理DBCP数据库连接池。
-
导入数据库连接池和数据库驱动
配置:
<!-- Bean属性注入的用途:利用Spring管理数据库连接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <!-- 利用DI功能注入String类型的基本值 --> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///db1"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="maxActive" value="10"/> </bean>
测试:
@Test public void testDataSource() throws Exception{ /* * Bean属性注入的用途:利用Spring管理数据库连接池 */ // DBCP 的 BasicDataSource 类实现了 // javax.sql.DataSource 接口,所以可以利用DataSource // 接口定义变量引用 BasicDataSource实例 DataSource ds = ctx.getBean("dataSource", DataSource.class); Connection conn = ds.getConnection(); String sql = "select 'Hello World!' as s"; Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sql); while(rs.next()) { System.out.println(rs.getString("s")); } conn.close(); }
Spring 读取 Properties
Spring支持读取Properties文件功能,用于获取配置文件参数。
案例:
-
编写配置文件 resource/jdbc.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8 username=root password=root maxActive=10
使用spring 读取:
<!-- 读取 Properties --> <util:properties id="jdbc" location="classpath:jdbc.properties"/>
测试:
@Test public void testProperties() { /* * 读取 Properties 文件 */ Properties cfg = ctx.getBean("jdbc",Properties.class); System.out.println(cfg); }
Spring 表达式
可以读取 Java Bean 属性,读取数组、List、Map、Properties等数据
假设 Bean 的 ID 是 demoBean 和 jdbc
- 读取"Bean属性"
- #{demoBean.num}
- #{demoBean.name}
- #{demoBean['price']}
- 读取数组
- #{demoBean.arr[0]}
- #{demoBean.city[1]}
- 读取Map、Properties
- #{jdbc.driver}
- #{jdbc['url']}
案例: 利用Spring表达式读取属性,注入到 testBean 中
编写 TestBean
public class TestBean { int value; String str; String driver; String city; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public String getStr() { return str; } public void setStr(String str) { this.str = str; } public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "TestBean [value=" + value + ", str=" + str + ", driver=" + driver + ", city=" + city + "]"; } }
配置
<!-- 利用Spring表达式读取信息,注入到TestBean --> <bean id="testBean" class="day02.TestBean"> <property name="value" value="#{demoBean.num}"/> <property name="city" value="#{demoBean.city[0]}"></property> <property name="str" value="#{demoBean.arr[0]}"/> <property name="driver" value="#{jdbc.driver}"/> </bean>
测试:
@Test public void testSpringEx() { /* * 测试:使用Spring表达式读取Bean属性 */ TestBean bean = ctx.getBean("testBean",TestBean.class); System.out.println(bean); }
使用Spring 表达式配置 DBCP 连接池
-
配置
<!-- 使用 Properties 文件 + Spring表达式配置 DataSource 连接池 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="#{jdbc.driver}"/> <property name="url" value="#{jdbc.url}"/> <property name="username" value="#{jdbc.username}"/> <property name="password" value="#{jdbc.password}"/> <property name="maxActive" value="#{jdbc.maxActive}"/> </bean>
测试:
@Test public void testDS() throws Exception{ /* * Spring 表达式配置JDBC连接池 */ DataSource ds = ctx.getBean("ds", DataSource.class); Connection conn = ds.getConnection(); String sql = "select 'Hello World!' as s"; Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sql); while(rs.next()) { System.out.println(rs.getString("s")); } conn.close(); }
基于注解扫描的IOC组件管理
Spring 提供了基于注解扫描的组件管理,支持Java EE标准注解。
-
导入包:
2.配置XML:
<!-- 开启注解扫描功能,扫描day02包以及子包 --> <context:component-scan base-package="day02"/>
3.编写Bean组件类
@Component public class HelloBean { @Override public String toString() { return "Hello World!"; } }
4.测试:
@Test public void testHelloBean() { /* * 测试注解组件扫描方式创建Bean对象 */ HelloBean bean = ctx.getBean("helloBean", HelloBean.class); System.out.println(bean); }
Spring 支持多种注解创建Bean组件
这些注解功能基本相同:
@Component @Named @Service @Repository @Controller
案例 @Repository 声明组件:
-
定义Bean组件
@Repository public class MyBean { @Override public String toString() { return "myBean"; } }
2.测试
@Test public void testRepository() { /* * 测试注解 Repository */ MyBean bean=ctx.getBean("myBean", MyBean.class); System.out.println(bean); }
注解可以自定义Bean ID
案例:
-
编写Bean