Spring框架——关于IOC容器和注解的36个小实验

实验1:通过IOC容器创建对象,并为属性赋值★

<bean id="page"  class="com.neuedu.Bean.Page">

<property name="fontSize" value="大写"></property>

<property name="fontNum" value="12"></property>

</bean>

 

ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");

Page bean2 = (Page)iocContainer.getBean("page");

 

实验2:根据bean的类型从IOC容器中获取bean的实例★

<bean id="page"  class="com.neuedu.Bean.Page">

<property name="fontSize" value="大写"></property>

<property name="fontNum" value="12"></property>

</bean>

 

ApplicationContext iocContainer = new ClassPathXmlApplicationContext("applicationContext.xml");

Page bean2 = iocContainer.getBean(Page.class);

  

 

实验3:通过构造器为bean的属性赋值

<bean id="Book" class="com.neuedu.Bean.Book">

<!-- 以下为给带参构造器传送参数 -->

<constructor-arg value="123" ></constructor-arg>

<constructor-arg value="456" ></constructor-arg>

<constructor-arg value="789" ></constructor-arg>

</bean>

  

 

实验4:通过index属性指定参数的位置

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="num" value="123"></property>

<constructor-arg value="123" index="0"></constructor-arg>

<constructor-arg value="123" index="1"></constructor-arg>

<constructor-arg value="123" index="2"></constructor-arg>

</bean>

  

 

实验5:通过类型不同区分重载的构造器

<bean id="page"  class="com.neuedu.Bean.Page">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

  

 

实验6:通过p名称空间为bean赋值

<bean id="Book2"  parent="Book"

p:num="254"

 />

  

实验14:给bean的级联属性赋值

<bean id="page"  class="com.neuedu.Bean.Page">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="page" ref="page"></property>

</bean>

  

 

实验21:测试bean的作用域,分别创建单实例和多实例的bean

<bean id="page" scope="prototype" class="com.neuedu.Bean.Page">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

  

Scope属性:

Prototype:每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()的操作

Request:每次Http请求都会创建一个新的Bean, 仅适用于WebApplication环境

Session:每次创建一个session,创建对象,同一个Http Session共享一个Bean,不同的HttpSession使用不同的Bean。仅适用于WebApplication环境

Singleton:Spring容器中仅存在一个Bean实例,Bean以单例的方式存在

 

实验22:创建带有生命周期方法的bean

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" init-method="int" destroy-method="destroy">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

  

 

实验20bean之间的依赖 depends-on="order"被依赖的对象会先创建

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" depends-on="font">

<constructor-arg value="123" type="int"></constructor-arg>

<constructor-arg value="456" type="String"></constructor-arg>

</bean>

<bean id="font" class="com.neuedu.Bean.Font"></bean>

  

 

实验18:通过继承实现bean配置信息的重用

<bean id="Book"  class="com.neuedu.Bean.Book" 

p:name="四大名著"

p:num="258"

 />

 

 <bean id="Book2"  parent="Book"

p:num="254"

 />

  

 

实验19:通过abstract属性创建一个模板bean

<bean id="Book"  abstract="true" class="com.neuedu.Bean.Book" 

p:name="四大名著"

p:num="258"

 />

 

 <bean id="Book2"  parent="Book"

p:num="254"

 />

  

 

实验7:测试使用null

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" >

<property name="fontSize">

<null/>

</property>

</bean>

  

null只有包装类和引用类型可以用

 

实验8:引用其他bean

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="page" ref="page"></property>

</bean>

  

 

实验9:引用内部bean

<bean id="Book" class="com.neuedu.Bean.Book">

<property name="page" >

<bean id="page" scope="singleton" class="com.neuedu.Bean.Page" >

<property name="fontSize" value="123"></property>

</bean>

</property>

</bean>

  

 

实验10:使用List类型的集合属性

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petList" ref="petList" />

</bean>

 

<util:list id="petList" list-class="java.util.ArrayList" value-type="java.lang.String">

<value>DOG</value>

<value>CAT</value>

<value>BIRD</value>

</util:list>

  

 

实验11:使用Map类型的集合属性

<!-- 第一种写法 ,通过ref引用,此时需要在 uitl-map中声明id 推荐这种写法

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petMap" ref="petMap" />

</bean>

<util:map id="petMap" map-class="java.util.HashMap">

<entry key="101" value="dog" />

<entry key="103" value="wolf" />

<entry key="105" value="bird" />

</util:map> --> 

 

<!-- 第二种写法,嵌入内部 -->

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petMap">

<util:map map-class="java.util.HashMap">

<!-- 可以通过map-class显示指定Map的实现类 -->

<entry key="101" value="dog" />

<entry key="103" value="wolf" />

<entry key="105" value="bird" />

</util:map>

</property>

</bean>

  

 

实验12:使用prop子元素为Properties类型的属性赋值

<bean id="pets" class="com.xgj.ioc.inject.construct.utilSchema.Pets"> <property name="petProperties" ref="petProperties" />

</bean>

 

<util:properties id="petProperties">

<prop key="151">PIG</prop>

<prop key="153">PINGUIN</prop>

</util:properties>

  

 

 

实验15:配置通过静态工厂方法创建的bean[通过静态方法提供实例对象,工厂类本身不需要实例化!]

<bean id="staticFactory" class="com.neuedu.spring.bean.StaticFactory" factory-method="getBook">

<constructor-arg value="book01"></constructor-arg>

</bean>

  

 

实验16:配置通过实例工厂方法创建的bean[通过实例方法提供实例对象,工厂类本身需要先创建对象!]

<bean id="instanceFactory" class="com.neuedu.spring.bean.InstanceFactory"></bean>

<bean id="bookFromInstanceFactory" factory-bean="instanceFactory" factory-method="getBook">

<constructor-arg value="book02"></constructor-arg>

</bean>

  

 

实验17:配置FactoryBean

public class MyFactoryBean implements FactoryBean<Book> {

 

@Override

public Book getObject() throws Exception {

return new Book(22, "无字天书", "好啊", 22.5);

}

 

@Override

public Class<?> getObjectType() {

return Book.class;

}

 

@Override

public boolean isSingleton() {

return false;

}

}

  

 

实验22[补充]:测试bean的后置处理器

 

①在bean的初始化方法调用前后执行操作的专门的对象

②自定义后置处理器实现该接口:org.springframework.beans.factory.config.BeanPostProcessor

 

③在springmvc中配置一下该bean对象.

<bean class="com.neuedu.spring.bean.Book" init-method="init"></bean>

<bean id="myBeanPostProcessor" class="com.neuedu.spring.bean.MyBeanPostProcessor"></bean>

  

 

数据库连接池:

6) 数据库连接池

> 数据库连接池就是存放数据库连接(Connection)的集合

> 我们获取一个数据库连接是一个相对很麻烦的过程,

如果我们获取一个数据库连接,使用一次以后就给它关闭了

下一次再去使用的时候就要重新创建一个新的数据库连接。

> 所以我们提出了一个数据库连接池的概念,数据库连接池放的都是数据库连接(Connection

我们在去使用数据库连接时候,不用再去重新创建数据库连接,而是直接从池中获取,

使用完的数据库连接,也不是直接销毁,而是要放回到连接池。

>

数据库连接池的常见的属性:

 

初始连接数量:数据连接池创建以后,保存数据库连接的数量[50]

最小空闲连接数:数据库连接池最少得未使用的数据库连接的数量[10]

最大空闲连接数:数据库连接池最大闲置连接数,当闲置连接数满了以后,将不会有其他连接进入池

每次增加连接数:当数据库连接都被占用以后,一次性增加的数据库连接的个数[20]

最大连接数:数据库连接池的最大容量,当最大连接数饱和了,则不再创建新的数据库连接[100]

最大等待时间:当数据库连接池饱和以后,等待获取数据库连接的时间

 

> 常见的数据库连接池

- 所有的数据库连接池都需要实现DataSource,当使用数据库连接池是,我们便不再需要使用DriverManger获取数据库连接

而是使用DataSource

 - Connection getConnection()

- 从数据库连接池中获取数据库连接对象

 

1.DBCP

- DBCPApache出品的一款数据库连接

- DBCP依赖于commons-pool

- 使用DBCP需要导入两个jar包:

commons-dbcp-1.4.jar

commons-pool-1.5.5.jar

- 当我们通过数据库连接池获取数据库连接以后,我们所获取到数据库连接已经不是我们熟悉的那个Connection

数据库连接池对Connection对象进行了包装,它修改Connectionclose()方法,

再去调用close()数据库连接将不会真的关闭,而是要放回到数据库连接池中,供其他线程使用。

- 核心类:

BasicDataSourceFactory

 

2.C3P0(重点)

- C3P0使用的是XML作为配置文件

- 使用c3p0需要导入一个jar包:

c3p0-0.9.1.2.jar

- 导入c3p0的配置文件:

1.配置文件的名字:c3p0-cofig.xml

2.配置文件要求放到类路径下(src

- 核心类:

ComboPooledDataSource

- 注意:

DataSource就相当于池子,我们的数据库连接都是从DataSource中获取的,

如果程序中有多个DataSource的实例,那么我们说你还不如不用数据库连接池。

所以我们的DataSource在项目中应该只有一个实例。

 

 

实验23:引用外部属性文件★

jdbc.properties文件:

jdbc.user=root

jdbc.passowrd=123456

jdbc.url=jdbc:mysql://localhost:3306/test

jdbc.driver=com.mysql.jdbc.Driver

 

<context:property-placeholder location="classpath:jdbc.properties"/>

 

1.在目标属性上加@Value注解

@Value("${jdbc.user}")

private String username;

2.

<!-- 根据外部属性文件中的信息配置数据源 -->

<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="user" value="${jdbc.user}"></property>

<property name="password" value="${jdbc.passowrd}"></property>

<property name="jdbcUrl" value="${jdbc.url}"></property>

<property name="driverClass" value="${jdbc.driver}"></property>

</bean>

 

 

ComboPooledDataSource bean = ioc.getBean(ComboPooledDataSource.class);

Connection connection = bean.getConnection();

System.out.println(connection);

Statement st = connection.createStatement();

ResultSet rs = st.executeQuery("select * from stu");

while(rs.next()){

String string = rs.getString("name");

String string2 = rs.getString("school");

System.out.println(string+"==="+string2);

}

  

 

 

实验24:基于XML的属性装配

①手动装配

<!-- 属性的装配:手动装配 -->

<bean id="userService" class="com.neuedu.spring.bean.UserService"></bean>

<bean  id="userAction" class="com.neuedu.spring.bean.UserAction">

<property name="userService" ref="userService"></property>

</bean>

  

 

②自动装配

<!-- 1.按类型装配:byType -->

<!-- 首先检测当前bean中需要装配的属性的类型 -->

<!-- 然后在IOC容器中查找匹配这个类型的bean -->

<!-- 如果类型匹配的bean是唯一的,那么就将这个匹配的bean注入到userAction中 -->

 

<bean id="userService" class="com.neuedu.spring.bean.UserService"></bean>

<bean  id="userAction" autowire="byType" class="com.neuedu.spring.bean.UserAction"></bean>

 

<!-- 2.按bean的id值装配:byName -->

<!-- 首先检测当前bean中需要装配的属性的属性名,属性名是将setXxx()方法去掉set,首字母小写得到的 -->

<!-- 然后根据属性名作为id的值,在IOC容器中查找对应的bean -->

<!-- 如果能够找到,则将找到bean注入进去 -->

  

 

 

 

6SpEL简介【见WORLD文档---了解】

Spring Expression LanguageSpring表达式语言,简称SpEL。支持运行时查询并可以操作对象图。

JSP页面上的EL表达式、Struts2中用到的OGNL表达式一样,SpEL根据JavaBean风格的getXxx()setXxx()方法定义的属性访问对象图,完全符合我们熟悉的操作习惯。

 

6.1 基本语法

SpEL使用#{}作为定界符,所有在大框号中的字符都将被认为是SpEL表达式。

 

6.2 使用字面量

●整数:<property name="count" value="#{5}"/>

●小数:<property name="frequency" value="#{89.7}"/>

●科学计数法:<property name="capacity" value="#{1e4}"/>

String类型的字面量可以使用单引号或者双引号作为字符串的定界符号

<property name=namevalue="#{'Chuck'}"/>

<property name='name' value='#{"Chuck"}'/>

Boolean<property name="enabled" value="#{false}"/>

 

 

实验25[SpEL测试I]SpEL中使用字面量

实验26[SpEL测试II]SpEL中引用其他bean

实验27[SpEL测试III]SpEL中引用其他bean的某个属性值

实验28[SpEL测试IV]SpEL中调用非静态方法

实验29[SpEL测试V]SpEL中调用静态方法

实验30[SpEL测试VI]SpEL中使用运算符

 

 

8.使用注解配置bean

①声明bean的注解

@Component 将当前类声明为IOC容器中的一个普通的组件

@Controller 将当前类声明为IOC容器中的一个控制器组件

@Service 将当前类声明为IOC容器中的业务逻辑层组件

@Repository 将当前类声明为IOC容器中的一个持久化层组件

@ControllerAdvice

 

Spring根据上述注解其实并不能分辨当前类是否真的是一个控制器或Dao,即使标记的类和注解不对应也没有语法错误。

但在实际工作中,肯定要将专门的注解标记在对应的类上面。

 

②使用基于注解的bean的配置,需要额外导入一个jar包:spring-aop-4.0.0.RELEASE.jar

 

③需要设置自动扫描的包

< context:component-scan base-package ="com.neuedu.ioc.bean"/>

 

 

④使用注解后,默认按照类名首字母小写作为id的值,也可以使用value属性指定idvalue属性名也可以省略注解

注解 id值

@Component                    

public class CommonComponent {

}

  commonComponent

@Controller(value="neueduBookAction" )         

public class BookAction {

 

}

neueduBookAction

@Service("happyService" )                    

public class BookService {

 

}

 happyService

 

 

实验31:通过注解分别创建DaoServiceController

实验32:使用context:include-filter指定扫描包时要包含的类

实验33:使用context:exclude-filter指定扫描包时不包含的类

 

< context:component-scan base-package ="com.neuedu.ioc.bean"/>

[1]base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类。

[2]当需要扫描多个包时可以使用逗号分隔,

[3]如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例:

<context:component-scan base-package="com.neuedu.component" resource-pattern="autowire/*.class"/>

[4]包含与排除

<context:include-filter>子节点表示要包含的目标类

注意:通常需要与use-default-filters属性配合使用才能够达到“仅包含某些组件”这样的效果。

即:通过将use-default-filters属性设置为false,禁用默认过滤器,然后扫描的就只是include-filter中的规则

指定的组件了。

<context:exclude-filter>子节点表示要排除在外的目标类

component-scan下可以拥有若干个include-filtejrexclude-filter子节

 

⑤使用注解进行自动装配:@Autowired注解[好处就是:连getset方法都不用写!]

[1]首先检测标记了@Autowired注解的属性的类型

[2]根据类型进行装配

[3]如果指定类型的bean不止一个,那么根据需要被装配的属性的属性名做id的值,查找bean

[4]如果根据id值还是没有找到bean,可以使用@Qualifier注解手动指定要装配的beanid.

 

实验34:使用@Autowired注解实现根据类型实现自动装配★

实验34[补充1]:如果资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★

实验34[补充2]:如果根据成员变量名作为id还是找不到bean,可以使用@Qualifier注解明确指定目标beanid

实验36Autowired注解的required属性指定某个属性允许不被设置.

实验37:在类上使用注解@Scope可以指定对象是单实例还是多实例的!

 

posted @ 2017-08-29 20:11  Mr_zhaoz  阅读(543)  评论(0编辑  收藏  举报