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

1.创建静态工厂类

public class StaticFactory {

      private static HashMap<String, Book> map = null;

      static{
map = new HashMap<>();
map.put("book01", new Book("java", "you", 33.33));
map.put("book02", new Book("c++", "you", 66.66));
map.put("book03", new Book("c#", "you", 99.99));
} public static Book getBookById(String id){
return map.get(id);
}
}

工厂本身不创建对象,而是通过其提供的静态方法获取对象

<bean id="staticFactory" class="com.neuedu.spring.entity.StaticFactory" factory-method="getBookById">
<constructor-arg value="book02"></constructor-arg>
</bean>
如果不写 <constructor-arg> 会报 method="getBookById" 构造器需要参数的错误
所以通过<constructor-arg> 传一个参数
在 junitTest 中会获取到 book02 中的内容

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

实例工厂先创建一个工厂对象,然后通过工厂对象的方法获取一个实例
将静态工厂类中的方法复制,并修改为非静态方法 【去除static】

public class InstanceFactory {

      private  HashMap<String, Book> map = null;

      {
map = new HashMap<>();
map.put("book01", new Book("java", "you", 33.33));
map.put("book02", new Book("c++", "you", 66.66));
map.put("book03", new Book("c#", "you", 99.99));
} public Book getBookById(String id){ return map.get(id);
}
}
先给工厂类本身创建一个对象<bean id="instanceFactory" class="com.neuedu.spring.entity.InstanceFactory"></bean>
再给方法创建一个对象 ,bean中不用写 class ,写 factory-bean,依赖于 instanceFactory
此时需要一个工厂方法factory-method
还需要给工厂方法提供一个参数<constructor-arg value="book03">

<bean id="instanceFactory" class="com.neuedu.spring.entity.InstanceFactory"></bean>
<bean id="bookFromInstanceFactory" factory-bean="instanceFactory" factory-method="getBookById">
<constructor-arg value="book03"></constructor-arg>
</bean>

从实例中获取book03

public void test() {
Object bean = ioc.getBean("bookFromInstanceFactory");
System.out.println(bean);
}

实验3:配置FactoryBean

创建 MyFactoryBean 实现 FactoryBean<>接口
返回对象就是调用 getObject() 方法
public class MyFactoryBean implements FactoryBean<Book>{

      @Override
public Book getObject() throws Exception {
//Spring的IOC容器就是调用该方法返回的对象
return new Book("java", "you", 33.33);
} @Override
public Class<?> getObjectType() {
//返回对象的类型
return Book.class;
} @Override
public boolean isSingleton() {
return true;
}
}
<!-- 配置工厂bean -->
<bean id="myFactoryBean" class="com.neuedu.spring.entity.MyFactoryBean"></bean>

实验4:测试bean的后置处理器

在bean的初始化方法【init】调用前后执行操作的专门的对象
Object 代表 bean 对象,String 代表 bean 对象的 id
自定义后置处理器实现该接口:BeanPostProcessor
 
public class MyBeanPostProcessor implements BeanPostProcessor{

      @Override
public Object postProcessAfterInitialization(Object object, String beanId) throws BeansException {
System.out.println("After---"+object+"---"+beanId);
return object;
} @Override
public Object postProcessBeforeInitialization(Object object, String beanId) throws BeansException {
System.out.println("Before---"+object+"---"+beanId);
return object;
}
}

没有 bean 对象,后置处理器不会执行

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

如果只这么写的话,是不会输出什么的

所以在这之前需要创建一个 bean 对象

<bean id="book" class="com.neuedu.spring.entity.Book" init-method="init">
<property name="bookName" value="java"></property>
<property name="author" value="you"></property>
<property name="price" value="32.32"></property>
</bean>
<bean id="myBeanPostProcessor" class="com.neuedu.spring.entity.MyBeanPostProcessor"></bean>
在 Book 类中创建 init( ) 方法,输出“Book对象的初始化方法”
以 观察是否在对象的初始化方法之前和之后处理

bean对象属性的检查,属性名、属性类型是否规范


数据库连接池:
 
> 数据库连接池就是存放数据库连接(Connection)的集合
> 我们获取一个数据库连接是一个相对很麻烦的过程,
   如果我们获取一个数据库连接,使用一次以后就给它关闭了
   下一次再去使用的时候就要重新创建一个新的数据库连接
> 所以我们提出了一个数据库连接池的概念,数据库连接池放的都是数据库连接(Connection)
   我们在去使用数据库连接时候,不用再去重新创建数据库连接,而是直接从池中获取,
    使用完的数据库连接,也不是直接销毁,而是要放回到连接池。
 
> 数据库连接池的常见的属性:
   初始连接数量:数据连接池创建以后,保存数据库连接的数量
 
   最小空闲连接数:数据库连接池最少得未使用的数据库连接的数量
 
   最大空闲连接数:数据库连接池最大闲置连接数,当闲置连接数满了以后,将不会有其他连接进入池
 
   每次增加连接数:当数据库连接都被占用以后,一次性增加的数据库连接的个数
 
   最大连接数:数据库连接池的最大容量,当最大连接数饱和了,则不再创建新的数据库连接
 
   最大等待时间:当数据库连接池饱和以后,等待获取数据库连接的时间
 
> 常见的数据库连接池
      - 所有的数据库连接池都需要实现DataSource,当使用数据库连接池是,我们便不再需要使用DriverManger获取数据库连接而是使用DataSource。
      - Connection getConnection()
      - 从数据库连接池中获取数据库连接对象
 
1.DBCP
      - DBCP是Apache出品的一款数据库连接
      - DBCP依赖于commons-pool
      - 使用DBCP需要导入两个jar包:
             commons-dbcp-1.4.jar
             commons-pool-1.5.5.jar
      - 当我们通过数据库连接池获取数据库连接以后,我们所获取到数据库连接已经不是我们熟悉的那个Connection
         数据库连接池对Connection对象进行了包装,它修改Connection的close()方法
         再去调用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的实例,那么我们说你还不如不用数据库连接池。

实验5:引用外部属性文件

新建文件 jdbc.properties
 
properties 中都是键值对格式

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

<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
</bean>
加载了配置文件的地址location="classpath:jdbc.properties" ,所以${ }能直接使用
通过 bean 中的连接信息
可以直接从连接池获取连接 bean. getConnection()
@Test
public void test() throws SQLException {
DataSource bean = ioc.getBean(DataSource.class);
System.out.println(bean.getConnection());
}

执行查询操作

@Test
public void test() throws SQLException {
DataSource bean = ioc.getBean(DataSource.class);
Connection conn = bean.getConnection();
String sql = "select * from student";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()){
String name = rs.getString("name");
String email = rs.getString("email");
String school = rs.getString("school");
String score = rs.getString("score");
System.out.println(name+"--"+email+"--"+school+"--"+score);
}
}

补充:

用注解就不用get/set方法
新建一个 AController 类 ,属性是外部文件中的值,在类上加 Controller注解并导包【aop】
加个注解 Value,注解里用EL表达式获取外部文件每个值
@Controller
public class AController { @Value("${jdbc.username}")
private String username;
//${jdbc.username}将值赋给username
@Value("${jdbc.password}")
private String password; @Value("${jdbc.driver}")
private String driver; @Value("${jdbc.url}")
private String url; @Override
public String toString() {
return "AController [username=" + username + ", password=" + password + ", driver=" + driver + ", url=" + url
+ "]";
}
}
<context:component-scan base-package="com.neuedu"></context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties"/>
@Test
public void test01(){
AController bean = ioc.getBean(AController.class);
System.out.println(bean);
}

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

(1)手动配置
 
新建两个类,一个类中包含另一个类为属性,
<!-- 手动装配 -->
<bean id="userService" class="com.neuedu.spring.entity.UserService"></bean>
<bean id="userAction" class="com.neuedu.spring.entity.UserAction">
<property name="userService" ref="userService"></property>
</bean>
(2)自动装配
 
① byType :如果UserAction 类中的userService的属性类型 UserService可以在IOC容器中找到,成功
                    与userService名字无关,只与属性类型相关

<bean id="userService" class="com.neuedu.spring.entity.UserService"></bean>
<bean id="userAction" autowire="byType" class="com.neuedu.spring.entity.UserAction"></bean>
② byName:如果 UserAction 中有属性名为userService 就可以在IOC容器中找到
                    只看名字

<bean id="userService" class="com.neuedu.spring.entity.UserService"></bean>
<bean id="userAction" autowire="byName" class="com.neuedu.spring.entity.UserAction"></bean>

实验7:使用注解配置bean

(1)声明bean的注解
        @Component 将当前类声明为IOC容器中的一个普通的组件 ,
        @Controller 将当前类声明为IOC容器中的一个控制器组件 ,接受web前端请求
        @Service 将当前类声明为IOC容器中的业务逻辑层组件 ,
        @Repository 将当前类声明为IOC容器中的一个持久化层组件,
 
(2)使用基于注解的bean的配置,需要额外导入一个jar包:spring-aop-4.0.0.RELEASE.jar
(3)需要设置自动扫描的包
<context:component-scan base-package="com.neuedu"></context:component-scan>
三种写法:
(1)直接写类名
(2)类名首字母小写
(3)在@Controller 后 加上重定义的名字 ,如@Controller(value="asd")
          value 可省
@Test
public void test(){
// UserController bean = ioc.getBean(UserController.class);
// Object bean = ioc.getBean("userController");
Object bean = ioc.getBean("asd");
System.out.println(bean);
}

Spring根据上述注解其实并不能分辨当前类是否真的是一个Controller或Dao,因为标记的类和注解不对应也没有语法错误。也就是将 controller层的注解写成@Service 也没错,但在实际工作中,肯定要将专门的注解标记在对应的类上面。


实验8:通过注解分别创建Dao、Service、Controller

分别在以下三层,依次调用下一层的方法,最后在dao层输出一句话
在Test 中观察是否能输出那句话
@Controller
public class UserController {
@Autowired
private UserService userService; public void getStudentInfo(){
userService.getStudentInfo();
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao; public void getStudentInfo() {
userDao.getStudentInfo();
}
}
@Repository
public class UserDao {
public void getStudentInfo() {
System.out.println("enenenenen"); }
}
@Test
public void test(){
UserController bean = ioc.getBean(UserController.class);
bean.getStudentInfo();
}

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

             使用context:include-filter指定扫描包时要包含的类
 
expression 中写的是扫描包时不包含的类的全类名【注解的全类名】
<context:component-scan base-package="com.neuedu">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包及其子包中的所有类
 
use-default-filters 默认为true ,当为false 时,代表不再使用默认的过滤器,在IOC容器中都找不到了
但是include-filter 代表要扫描的包,所以在Test中可以在 IOC中找到controller
<context:component-scan base-package="com.neuedu" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
使用的是所建类的全类名,而不是 @Controller 的全类名
这样在 IOC容器中也找不到

<context:component-scan base-package="com.neuedu">
<context:exclude-filter type="aspectj" expression="com.neuedu.spring.entity.UserController"/>
</context:component-scan>

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

[1]首先检测标记了@Autowired注解的属性的类型
[2]根据类型进行装配
[3]如果指定类型的bean不止一个,那么根据需要被装配的属性的属性名做id的值,查找bean
[4]如果根据id值还是没有找到bean,可以使用 @Qualifier 注解手动指定要装配的bean的id
 
@Autowired 首先是根据类型来注入
根据 service 的类型到 IOC中找

@Controller
public class UserController {
@Autowired
private UserService service; public void say(){
service.getStudentInfo();
}
}
因为 service 的类型是 UserService ,所以当 UserService有一个子类的时候
根据类型就会找不到
所以就会通过姓名查找
通过更改 service层的value值

@Service(value="service")
public class UserService {
@Autowired
private UserDao userDao; public void getStudentInfo() {
userDao.getStudentInfo();
}
}
 
@Qualifier 指定一个value 值,去 IOC容器中找它
@Autowired(required=false) 指:就算找不到也不会报错

@Controller
public class UserController {
@Autowired(required=false)
@Qualifier(value="BService")
private UserService ser; public void say(){
ser.getStudentInfo();
}
}

Spring(二)--FactoryBean、bean的后置处理器、数据库连接池、引用外部文件、使用注解配置bean等的更多相关文章

  1. Spring的Bean的生命周期以及Bean的后置处理器

    Bean的生命周期: Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务. Spring IOC 容器对 Bean 的生命周期进 ...

  2. Spring中Bean的后置处理器

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/bean-post-processors.html: Bean后置处理器 BeanPostProce ...

  3. Spring源码之BeanFactoryPostProcessor(后置处理器)

    Spring源码之BeanFactoryPostProcessor(后置处理器). 有点水平的Spring开发人员想必都知道BeanFactoryPostProcessor也就是常说的后置管理器,这是 ...

  4. BeanPostProcessor bean 的后置处理器

    一. 自定 bean 的后置处理器 MyBeanPostProcessor 类.当你在初始化容器中的 bean 之前和之后,都会调用该处理器中的方法 @Component //将该后后置处理器加入到容 ...

  5. Spring Bean前置后置处理器的使用

    Spirng中BeanPostProcessor和InstantiationAwareBeanPostProcessorAdapter两个接口都可以实现对bean前置后置处理的效果,那这次先讲解一下B ...

  6. [原创]java WEB学习笔记101:Spring学习---Spring Bean配置:IOC容器中bean的声明周期,Bean 后置处理器

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. spring中Bean后置处理器实现总结

    BeanPostProcessor接口 bean的后置处理器实现功能主要是 可以在bean初始化之前和之后做增强处理.自定义MyBeanProcessor实现BeanPostProcessor接口,重 ...

  8. Spring Bean后置处理器

    本例子源于:W3CSchool,在此作记录 Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理. BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己 ...

  9. Spring Bean的生命周期、后置处理器、定义继承

    目录: 了解Spring的基本概念 Spring简单的示例 Spring Bean的定义及作用域 1.Bean的生命周期 Bean的生命周期可以简单的理解为:Bean的定义——Bean的初始化——Be ...

随机推荐

  1. Android - Fragment (一)定义

    什么是Fragment,为什么要用Fragment? Fragment,直译为碎片.是Android UI的一种. Fragment加载灵活,替换方便.定制你的UI,在不同尺寸的屏幕上创建合适的UI, ...

  2. 首页音乐播放器添加"多首音乐"

    添加音乐播放器可以去这个博主的网址参考学习 原文链接:http://www.cnblogs.com/RhinoC/p/4695509.html 以下是针对添加“多首音乐”的详细过程: (注:由于之前并 ...

  3. (转)Linux修改SSH登录欢迎语

    场景:感觉这样做挺个性的,做个记录! 1 Linux修改SSH的欢迎语 众所周知,Linux系统并没有像Windows一样自带远程桌面连接,虽然可以通过后期安装VNC之类的软件来弥补这个缺点,但用了L ...

  4. 【CSS】整屏大背景

    1. 利用div的层次,设置底层div充满屏幕,并给div设置背景图 <div id="Layer1" style="position:absolute;top:0 ...

  5. 使用Node.js搭建静态资源服务器

    对于Node.js新手,搭建一个静态资源服务器是个不错的锻炼,从最简单的返回文件或错误开始,渐进增强,还可以逐步加深对http的理解.那就开始吧,让我们的双手沾满网络请求! Note: 当然在项目中如 ...

  6. [补档]Cube

    Cube 题目 给你一个n×m的棋盘,有一个1×1×2的长方体竖直放在(1,1)上,你可以将其在棋盘上滚动,你的目标是让其竖直放在(n,m)上,问至少需要多少次操作.(放倒.竖直.翻滚) INPUT ...

  7. seajs的模块化开发--实践笔记

    2017-04-02 SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制.有效的解决复杂项目中命名冲突.依赖.性能等问题. SeaJS ...

  8. Pandas 操作

    一.Series的创建: pd.Series([ 数据 ]) In [17]: import pandas as pd In [18]: import numpy as np In [19]: s = ...

  9. mysql忘记密码,修改密码重新安装的一些问题

    前言 想要装cobra,却意外发现mysql连接失败,命令行连一下发现无论怎么样都连不上了. 我能想到的密码都用上了,糟糕!看来只能修改密码,或者重装了. 最后是重装搞定的,当然也发现了正确的修改密码 ...

  10. 35. Search Insert Position【leetcode】

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...