Spring4入门之第二章IOC的注解

Spring4入门之第二章IOC的注解

Spring整合数据库连接池

传统硬编码方式使用连接池

  • 硬编码:

    可以看出无论是哪个连接池都比较繁琐,复用性和可扩展性都很差

    我们可以将其进一步的升级和Spring进行简单的整合

    //C3p0的硬编码方式:
    public void demo1() throws PropertyVetoException, SQLException {
    		ComboPooledDataSource c3p0DataSource = new ComboPooledDataSource();
    
    		c3p0DataSource.setDriverClass("com.mysql.jdbc.Driver");
    		c3p0DataSource.setJdbcUrl("jdbc:mysql:///sh_day04");
    		c3p0DataSource.setUser("root");
    		c3p0DataSource.setPassword("root");
    
    		Connection conn = c3p0DataSource.getConnection();
    		System.out.println(conn);
    	}
    //DBCP的硬编码方式:
    public void demo2() throws SQLException {
    		BasicDataSource dbcpDataSource = new BasicDataSource();
    
    		dbcpDataSource.setDriverClassName("com.mysql.jdbc.Driver");
    		dbcpDataSource.setUrl("jdbc:mysql:///sh_day04");
    		dbcpDataSource.setUsername("root");
    		dbcpDataSource.setPassword("root");
    
    		Connection conn = dbcpDataSource.getConnection();
    		System.out.println(conn);
    	}
    
  • Spring和数据库连接池进行简单的整合

    上面的硬编码方式我们可以将对象的创建权和属性的注入全部交给Spring进行管理(IOC和DI)

    比如:ComboPooledDataSource c3p0DataSource = new ComboPooledDataSource();(外部类对象的创建)

    ​ c3p0DataSource.setDriverClass(“com.mysql.jdbc.Driver”);(属性的注入)

    我们可以在Spring容器的配置文件中

    配置:如下代码

    applicationContext.xml

    	<!-- Spring整合C3P0数据库连接池的普通方式 -->
    	<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    		<property name="driverClass" value="com.mysql.jdbc.Driver" />
    		<property name="jdbcUrl" value="jdbc:mysql:///sh_day04" />
    		<property name="user" value="root" />
    		<property name="password" value="root" />
    	</bean>
    	<!-- Spring整合DBCP数据库连接池的普通方式 -->
    	<bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">
    		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    		<property name="url" value="jdbc:mysql:///sh_day04"/>
    		<property name="username" value="root"/>
    		<property name="password" value="root"/>
    	</bean>
    

    编写测试代码:

    public void demo3() throws SQLException {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //C3P0
    		DataSource c3p0DataSource = (ComboPooledDataSource) applicationContext.getBean("c3p0");
          //DBCP
        	DataSource dbcpDataSource = (BasicDataSource) applicationContext.getBean("dbcp");
        
    		Connection connC3P0 = c3p0DataSource.getConnection();
        	Connection connDBCP = dbcpDataSource.getConnection();
    
    		System.out.println(connC3P0);
        	System.out.println(connDBCP);
    	}
    

整合使用数据库连接池

  • 对于上面的两种方式,无论哪一种,代码的可扩展性都非常差

  • 于是我们可以使用将数据库的连接等信息以配置文件的方式让Spring区进行加载

  • 步骤思想:

    1. 将数据库的连接Driver、url、user和password等等,以配置文件jdbc.properties的方式脱离applicationContext.xml文件
    2. Spring通过什么标签或者功能去读取jdbc.properties
    3. 如何通过jdbc.properties文件动态获取里面的数据,并使Spring动态的和获取
  • 问题解答:

    1. jdbc.properties文件:

      #mysql
      
      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql:///sh_day04
      jdbc.username=root
      jdbc.password=root
      
      #Oracle
      
      #jdbc.driver=oracle.jdbc.OracleDriver
      #jdbc.url=jdbc:oracle:thin:@192.168.0.X:1521:xe
      #jdbc.username=root
      #jdbc.password=root
      
      
      #DB2
      
      #jdbc.driver=com.ibm.db2.jcc.DB2Driver
      #jdbc.url=jdbc:db2://localhost:50000/toolsdb
      #jdbc.username=root
      #jdbc.password=root
      
    2. Spring通过标签:可以读取到classpath(src下)的jdbc.properties文件

      <context:property-placeholder location="classpath:jdbc.properties" />
      
    3. 然后通过${}表达式获取Spring已经读取到的jdbc.properties文件中的属性值

      	<!-- Spring整合数据库连接池的最终方式 -->
      	<context:property-placeholder location="classpath:jdbc.properties" />
      	
      	<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      		<property name="driverClass" value="${jdbc.driver}" />
      		<property name="jdbcUrl" value="${jdbc.url}" />
      		<property name="user" value="${jdbc.username}" />
      		<property name="password" value="${jdbc.password}" />
      	</bean>
      
      	<bean id="dbcp" 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}"/>
      	</bean>
      

Spring整合Junit测试

  • 普通测试的缺点:

    代码复用性太大

    配置文件运行一次加载一次

  • Spring整合Junit开发的步骤:

    1. 导包:

      spring-test.jar :增强
      spring-aop.jar :可以写注解
      junit.jar :之前的测试

    2. 要告诉spring谁加载配置文件 (SpringJunt4ClassRunner.class)

    3. 通知spring配置文件的地址

    4. 分层测试

  • 在Spring中spring-test.jar包中对Junit进行了加强,Spring通过SpringJunt4ClassRunner加载配置文件,同时对于Junit本身测试的一部分不改动

在这里插入图片描述

  • 两个注解

    1. @ContextConfiguration(“classpath:applicationContext.xml”)(告诉Spring配置文件的位置)
    2. @RunWith(value = SpringJUnit4ClassRunner.class)(告诉Spring谁去加载配置文件)
  1. 导包 在Spring3之后需要导入spring-aop.jar

  2. 开启注解扫描器 告诉spring应该去那个包下面解析注解,使用IOC的注解开发,配置扫描(哪些包下的类使用IOC注解)!!!扫描是为了扫描类上的注解

    <context:component-scan base-package="com.syj.spring" />
    
  3. 配置注解组件 Component

  4. 测试(使用上面的数据库连接池)

    //告诉Spring配置文件的位置
    @ContextConfiguration("classpath:applicationContext.xml")
    //告诉Spring谁去加载配置文件
    @RunWith(value = SpringJUnit4ClassRunner.class)
    public class SpringJunit {
    	@Resource(name = "c3p0")
    	private DataSource c3p0DataSource;
    
    	@Resource(name = "dbcp")
    	private DataSource dbcpDataSource;
    
    	@Test
    	public void demo1() throws SQLException {
    
    //		Connection connection = c3p0DataSource.getConnection();
    		Connection connection = dbcpDataSource.getConnection();
    		System.out.println(conection);
    	}
    }
    

注解的开发

类上的注解<bean id="" class="" />

  • @Component(“bean的id值”) 定义在类上 只要定义在了类上

  • 那么注解扫描器只要一扫描到就会创建该类的实例对象 放在spring容器中

  • spring发布了公告, @Component这个注解不维护了,要维护这个注解下面衍生出的3个注解

    注解描述
    @Controller(“bean的id值”)针对的就是web层
    @Service(“bean的id值”)针对的是service层
    @Repository(“bean的id值”)针对的是dao层

属性值的注解

  • @Value(“属性值”),定义在属性字段上,针对的是基本类型和String类型

    ​ 如果使用了这个注解 该属性的set方法可以省略不写(如果写了set方法注解写在set方法上面,没有set方法直接写在属性上)

  • @Autowired类型。 定义在属性字段上的 ,针对的是对象类型

    ​ 如果定义在了那个对象类型的属性身上,会自动去spring容器中找该类型的实例对象给赋值

  • @Qualifier(“userDaoxxx”)名称。定义在属性字段上的,指定用该类型的哪个id名称的实例对象

  • @Resource(name=“userDaoxxx”)
    @Autowired+@Qualifier(“userDaoxxx”)

  • @Autowired针对的类型Autowired和Qualifier决定属性的名称应该保持一致。这两个的用法和Resource的用法效果一样,应该和属性id一致。

  • 但是真正在使用开发中@Autowired比@Resource使用的多

需要了解的注解

  • @Scope("singleton"或则prototype):定义在类上的 指定当前类是单实例还是多实例

  • @PostConstruct:定义在方法上 配置初始化方法

  • @PreDestroy:定义在方法上 配置销毁的方法

Spring的新注解(完全代替XML方式)

  • 完全用注解的方式 完全抛弃掉xml配置文件

  • 半注解半xml方式:
    别人的类用xml
    自己的类用注解

  • 全注解方式:
    别人类要用注解
    自己的类也要用注解

  • 条件: 需要有一个注解类,不在加载配置文件 而是加载这个注解类

Service调Dao全注解方式(自己的类)

  • 使用到的注解

    1. @Repository(“userDao”)—>创建一个UserDaoImpl的实现类(Spring new UserDaoImpl())
    2. @Service(“userService”)—>创建一个userServiceImpl的实现类(Spring new UserServiceImpl())
    3. @Value(“猪八戒”)—>在UserDao的实现类UserDaoImpl中给name属性注入“猪八戒”值
    4. @Resource(“userDao”)—>在userServiceImpl的类中给UserDao属性进行(对象)赋值
  • 使用全注解的步骤:

    1. 创建一个注解类(代表这个注解类就类比于applicationContext.xml文件)在applicationContext.xml文件可以编写的基本都可以找到对应的注解代替

    2. 在applicationContext.xml中的配置扫描包,的注解代替@ComponentScan

      @ComponentScan(basePackages = “com.syj.spring”) 相当于:

      <context:component-scan base-package="com.syj.spring" />
      
  • 编写注解类

    @Configuration // 表示该类是一个注解类
    @ComponentScan(basePackages = "com.syj.spring") // 代替<context:component-scan base-package="com.syj.spring" />
    public class SpringAnnotationClass {
    
    }
    
  • 编写测试

    @Test
    	public void dmeo1() {
            //加载注解类
    		ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
    				SpringAnnotationClass.class);
    		UserService userService = (UserService) annotationConfigApplicationContext.getBean("userService");
    		userService.save();
    	}
    
  • 流程详解:

    1. 当在测试代码中加载pplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
      SpringAnnotationClass.class);的时候,Spring会去加载该类(发现时是注解类)
    2. 执行到注解@ComponentScan(basePackages = “com.syj.spring”) 的时候开始扫描com.syj.spring包下的所有子包的类在并执行相应的注解,
    3. 因为在UserDaoImpl和UserServiceImpl有注解存在,所以创建了对象的实例和注入了相应的属性
    4. 取出指定的属性并执行相应的程序代码

C3P0数据库连接池全注解方式(外部引入的类)

  • 目的将Spring和数据库连接池整合的修改为全注解方式

  • 需要改为注解的在applicationContext.xml中的位置

    1. 加载jdbc.properties配置文件的标签

      <context:property-placeholder location="classpath:jdbc.properties" />
      
    2. 交给Spring创建的C3P0核心实现类ComboPooledDataSource

      <bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      </bean>
      
    3. 从jdbc.properties配置文件中动态获取连接数据库的属性

          <property name="driverClass" value="${jdbc.driver}" />
          <property name="jdbcUrl" value="${jdbc.url}" />
          <property name="user" value="${jdbc.username}" />
          <property name="password" value="${jdbc.password}" />
      
    4. ${}的加载

  • 注解代替:

    1. 使用@propertySource(value=“classpath:jdbc.properties”)相当于在applicationContext.xml文件中配置

      <context:property-placeholder location="classpath:jdbc.properties" />
      
    2. 在注解类中创建一个使用C3P0返回数据源的方法,并交给Spring进行管理

      	// 配置别人的类,将其加载进来
      	// 这也是为什么不愿意使用全注解的(有的地方复杂)
      @Bean(name = "c3p0") // 相当于:<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"/>   起名相当于自己管理
      	public DataSource getDataSource() throws PropertyVetoException {
      		ComboPooledDataSource ds = new ComboPooledDataSource();
      
      		ds.setDriverClass(driver);
      		ds.setJdbcUrl(url);
      		ds.setUser(username);
      		ds.setPassword(password);
      		return ds;
      	}
      
    3. 在注解类中创建数据库连接池的属性使用注解@value进行属性注入

      	@Value("${jdbc.driver}")
      	private String driver;
      	
      	@Value("${jdbc.url}")
      	private String url;
      	
      	@Value("${jdbc.username}")
      	private String username;
      	
      	@Value("${jdbc.password}")
      	private String password;
      
    4. 在4.3以前要给Spring配置一个解析器来解析${}

    @Bean // 不加任何()内容代表交给Spring管理
    	public static PropertySourcesPlaceholderConfigurer creatPropertySourcesPlaceholderConfigurer() {
    		return new PropertySourcesPlaceholderConfigurer();
    	}
    
    1. 此时已经将Spring整合数据库连接池从配置文件中脱离出来(亲测有效)

    2. 注解类的完整代码:

      package com.syj.spring.demo6;
      
      import java.beans.PropertyVetoException;
      
      import javax.sql.DataSource;
      
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.ComponentScan;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.PropertySource;
      import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
      
      import com.mchange.v2.c3p0.ComboPooledDataSource;
      
      @Configuration // 表示该类是一个注解类
      @ComponentScan(basePackages = "com.syj.spring") // 代替<context:component-scan base-package="com.syj.spring" />
      @PropertySource(value = "classpath:jdbc.properties") // <context:property-placeholder
      														// location="classpath:jdbc.properties" />
      public class SpringAnnotationClass {
      
      	@Value("${jdbc.driver}")
      	private String driver;
      	@Value("${jdbc.url}")
      	private String url;
      	@Value("${jdbc.username}")
      	private String username;
      	@Value("${jdbc.password}")
      	private String password;
      
      	// 配置别人的类,将其加载进来
      	// 这也是企业为什么不愿意使用全注解的
      	@Bean(name = "c3p0") // 相当于:<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"
      							// />起名相当于自己管理
      	public DataSource getDataSource() throws PropertyVetoException {
      		ComboPooledDataSource ds = new ComboPooledDataSource();
      
      		ds.setDriverClass(driver);
      		ds.setJdbcUrl(url);
      		ds.setUser(username);
      		ds.setPassword(password);
      		return ds;
      	}
      
      	// 4.3以前要给Spring配置一个解析器来解析${}
      	@Bean // 不加任何()内容代表交给Spring管理
      	public static PropertySourcesPlaceholderConfigurer creatPropertySourcesPlaceholderConfigurer() {
      		return new PropertySourcesPlaceholderConfigurer();
      	}
      }
      
    3. 测试代码

      @Test
      	public void dmeo2() throws SQLException {
      		ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
      				SpringAnnotationClass.class);
      		DataSource ds = (DataSource) annotationConfigApplicationContext.getBean("c3p0");
      		System.out.println(ds.getConnection());
      	}
      
  • 流程详解

    1. 在执行到ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
      SpringAnnotationClass.class);时。Spring会主动寻找该类,并加载
    2. 因为注解类上别的注解的存在,所以会加载依次加载@ComponentScan(basePackages = “com.syj.spring”) ,创建一系列的实例对象。
    3. 同时通过@PropertySource(value = “classpath:jdbc.properties”) 告诉Spring要加载的配置文件jdbc.properties
    4. 之后便通过属性注入为数据库连接池中的driver,url,username和password赋值(加载${}解析器)
    5. 同时将别人的类C3P0加载进Spring容器,并命名为c3p0
    6. 获取数据源对象
    7. 租后进行一系列的数据库的交互
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值