Spring ioc和DI注入注解開發(fā)

一.Spring的API -ApplicationContext

1.1,ApplicationContext的繼承體系

applicationContext: 接口類型,代表應(yīng)用上下文,可以通過(guò)其 實(shí)例 獲得Spring容器中的bean對(duì)象

1.2,ApplicationContext的實(shí)現(xiàn)類

1)ClassPathXmlApplicationContext
        它是從**類的根路徑下(target/classes)**加載配置文件
2)FileSystemXmlApplicationContext
        它是從**磁盤路徑上**加載配置文件,配置文件可以在磁盤的任意位置
3)AnnotationConfigApplicationContext
        當(dāng)使用注解配置容器對(duì)象時(shí),需要使用此類來(lái)創(chuàng)建spring容器.使用它來(lái)讀取注解.

1.3,getBean()方法使用

    public Object getBean(String name) throws BeansException{
             assertBeanFactoryActive();
            return getBeanFactory().getBean(name);
    }

    public <T> T getBean(Class<T> requiredType) throws BeansException{
               assertBeanFactoryActive();
                return getBeanFactory().getBean(requiredType);
    }
    //其中, 當(dāng)參數(shù)的數(shù)據(jù)類型時(shí)字符串時(shí), 表示根據(jù)Bean的id從容器中獲得Bean實(shí)例,返回Object,需要強(qiáng)轉(zhuǎn).
    //當(dāng)參數(shù)的數(shù)據(jù)類型時(shí)class類型時(shí), 表示根據(jù)類型從容器中匹配Bean實(shí)例, 當(dāng)容器中相同類型的Bean有多個(gè)時(shí),則此方法會(huì)報(bào)錯(cuò)

getBean()方法使用

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //參數(shù)的數(shù)據(jù)類型時(shí)字符串
    UserService userService = (UserService)applicationContext.getBean("userService");
    //參數(shù)的數(shù)據(jù)類型時(shí)class類型
    UserService userService2 = applicationContext.getBean(UserService.class);


二,Spring配置數(shù)據(jù)源(數(shù)據(jù)庫(kù)連接池)dataSource

2.1 數(shù)據(jù)源(連接池)的作用

減少頻繁的請(qǐng)求連接,釋放資源
數(shù)據(jù)源(連接池)是提高程序性能而出現(xiàn)的, 事先實(shí)例化數(shù)據(jù)源, 初始化部分連接資源.使用連接資源時(shí)從數(shù)據(jù)源中獲取,使用完畢后將連接資源歸還給數(shù)據(jù)源
常見(jiàn)的數(shù)據(jù)源(連接池):DBCP C3P0 BoneCP Druid等.
開發(fā)步驟:
1) 導(dǎo)入數(shù)據(jù)源的坐標(biāo)和數(shù)據(jù)庫(kù)驅(qū)動(dòng)坐標(biāo)
2) 創(chuàng)建數(shù)據(jù)源對(duì)象
3) 設(shè)置數(shù)據(jù)源的基本連接數(shù)據(jù)
4) 使用數(shù)據(jù)源獲取連接資源和歸還連接資源

2.2 數(shù)據(jù)源的手動(dòng)創(chuàng)建方式

1_C3P0連接池的創(chuàng)建

1)導(dǎo)入c3p0的坐標(biāo)(依賴)

    <!--pom配置中引入c3p0坐標(biāo)(依賴)-->
    <!--c3p0連接池-->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</actifactId>
        <version>0.9.1.2</version>
    </dependency>
    
2)導(dǎo)入數(shù)據(jù)庫(kù)mysql驅(qū)動(dòng)坐標(biāo)
    
    <!--pom配置中引入mysql驅(qū)動(dòng)-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</actifactId>
        <version>5.1.39</version>
    </dependency>
    
3)創(chuàng)建c3p0連接池對(duì)象
    
    @Test
    public void testC3P0() throws Exception{
        //創(chuàng)建數(shù)據(jù)源
        ComboPoolDataSource dataSource = new CombopoolDataSource();
        //設(shè)置數(shù)據(jù)庫(kù)連接參數(shù)
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        //獲得連接對(duì)象
        Connection conn = dataSource.getConnection();
        System.out.printLn(conn);
    }

2_Druid連接池的創(chuàng)建

1)、導(dǎo)入Druid連接池坐標(biāo)
<!-- Druid連接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

2)、導(dǎo)入mysql數(shù)據(jù)庫(kù)驅(qū)動(dòng)坐標(biāo)
<!-- mysql驅(qū)動(dòng) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.39</version>
</dependency>

3)、創(chuàng)建Druid連接池
@Test
public void testDruid() throws Exception {
    //創(chuàng)建數(shù)據(jù)源
    DruidDataSource dataSource = new DruidDataSource();
    //設(shè)置數(shù)據(jù)庫(kù)連接參數(shù)
    dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
    dataSource.setUrl("jdbc:mysql://localhost:3306/test");   
    dataSource.setUsername("root");
    dataSource.setPassword("root");
    //獲得連接對(duì)象
    Connection connection = dataSource.getConnection();    
    System.out.println(connection);
}

3、提取jdbc.properties配置文件,并讀取配置文件創(chuàng)建連接池

//提取配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

//使用ResourceBundle加載resource文件 ResourceBundle資源捆綁
@Test
public void testByProperties() throws Exception{
    //加載類路徑下jdbc.properties
    ResourceBundle rb = ResourceBundle.getBundle("jdbc");
    //創(chuàng)建連接池
    //c3p0數(shù)據(jù)源
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    //druid數(shù)據(jù)源
    DruidDataSource dataSource = new DruidDataSource();
    
    //設(shè)置數(shù)據(jù)源屬性
    dataSource.setDriverClass(rb.getString("jdbc.driver"));   
    dataSource.setJdbcUrl(rb.getString("jdbc.url")); 
    dataSource.setUser(rb.getString("jdbc.username")); 
    dataSource.setPassword(rb.getString("jdbc.password"));
    Connection connection = dataSource.getConnection();   
    System.out.println(connection);
}

2.3Spring配置數(shù)據(jù)源

Spring配置數(shù)據(jù)源就是將DataSource的創(chuàng)建全交給Spring容器去完成

  • DataSource有參/無(wú)參構(gòu)造方法,Spring默認(rèn)是通過(guò)無(wú)參構(gòu)造方法實(shí)例化對(duì)象
  • DataSource set方法進(jìn)行字符串注入
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
</bean>

測(cè)試從容器中獲取數(shù)據(jù)源連接

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource)applicationContext.getBean("dataSource");
Connection connection = dataSource.getConnection();
System.out.println(connection);

2.4抽取jdbc配置文件

applicationContext.xml加載jdbc.properties配置文件獲得連接信息。

首先,需要引入context命名空間和約束路徑:

命名空間:xmlns:context="http://www.springframework.org/schema/context"

約束路徑:http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" 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>

三,Spring注解開發(fā)

注解的時(shí)候, set方法可以省略

3.1 Spring原始注解

Spring原始注解主要是代替xml中<bean>的配置

注解 說(shuō)明
@Component 使用在類上 用于實(shí)例化Bean
@Controller 使用在web層類上 用于實(shí)例化Bean
@Service 使用在service層 用于實(shí)例化bean
@Repository 使用在dao層上 用于實(shí)例化bean,實(shí)現(xiàn)類只有一個(gè)的話,不用注入id
@Autowired 使用在字段上用于根據(jù)類型依賴注入,按照數(shù)據(jù)類型從spring匹配
@Qualifier 結(jié)合@Autowired一起使用,用于根據(jù)名稱進(jìn)行依賴注入,是按照id的值,從容器開始匹配的.實(shí)現(xiàn)類不唯一時(shí)必須結(jié)合@qualifier使用
@Resource 按照名稱進(jìn)行注入,相當(dāng)于@Autowired+@Qualifier
@Value 注入普通屬性
@Scope 標(biāo)注Bean的作用范圍 singeton單例 prototype多例
@PostConstruct 使用在方法上標(biāo)注該方法是bean的初始化方法
@PreDestroy 使用在方法上標(biāo)注該方法是bean的銷毀方法

注意: 使用注解進(jìn)行開發(fā)時(shí),需要在applicationContext.xml中配置組件掃描,作用是指定哪個(gè)包及其子包下的bean需要進(jìn)行掃描以便識(shí)別使用注解配置的類 ,字段 和方法.

<!--注解的組件掃描-->
<context:component-scan base-package="cn.ppvir"/>

注解使用示例

//1.dao層 使用@Component組件或者@Repository表示  需要spring進(jìn)行實(shí)例化
//@Component("userDao")
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("save running... ...");
    }
}

//2.service層 使用@Component組件或者@Service標(biāo)識(shí) 需要spring進(jìn)行實(shí)例化
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {
    /*@Autowired
    @Qualifier("userDao")*/
    @Resource(name="userDao")
    private UserDao userDao;
    @Override
    public void save() {       
      userDao.save();
    }
}

//3.注入
//3.1 userDao注入 使用@Autowired 或者 @Autowired+@Qualifier 或者@Resource
public class UserServiceImpl implements UserService {
    /*@Autowired 自動(dòng)注入
    @Qualifier("userDao") 限定名稱*/
    @Resource(name="userDao") //按照名稱進(jìn)行注入
    private UserDao userDao;
    @Override
    public void save() {       
      userDao.save();
    }
}
//3.2 普通字符串注入 使用@Value
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Value("注入普通數(shù)據(jù)")//普通字符串注入
    private String str;
    @Value("${jdbc.driver}")//普通字符串注入
    private String driver;
    @Override
    public void save() {
        System.out.println(str);
        System.out.println(driver);
        System.out.println("save running... ...");
    }
}

//4.標(biāo)注bean的范圍  單例或者多例 使用@Scope("singleton") 或者 @Scope("prototype")

//5.初始化和銷毀標(biāo)注  使用@PostConstruct   @PreDestroy
@PostConstruct
public void init(){
    System.out.println("初始化方法....");
}
@PreDestroy
public void destroy(){
    System.out.println("銷毀方法.....");
}

3.2 Spring新注解

原始注解不能替代全部xml配置文件,還需要使用注解替代的配置如下:

  1. 非自定義的bean的配置: <bean>
  2. 加載properties文件的配置:<context:property-placeholder location="classpath:jdbc.properties"/>
  3. 組件掃描的配置:<context:component-scan base-package="cn.ppvir"/>
  4. 引入其他文件:<import resource="classpath:applicationContext.xml"></import>
注解 說(shuō)明
@Configuration 用于指定當(dāng)前類是一個(gè)spring配置類,當(dāng)創(chuàng)建容器是會(huì)從該類上加載注解
@ComponentScan 用于指定Spring在初始化容器時(shí)要掃的包,作用與在xml配置文件中的<context:component-scan>一樣
@Bean 使用在方法上,標(biāo)注將該方法的返回值存儲(chǔ)到spring容器中
@PropertySource 用于加載配置文件中的配置
@Import 用于導(dǎo)入其他配置類

新注解使用示例:

  1. @Configuration | @ComponentScan | @Import
/*總配置類*/
@Configuration
@ComponentScan("com.itheima")//掃包
@Import({DataSourceConfiguration.class})//加載分配置  數(shù)組形式
public class SpringConfiguration {
}
  1. @propertySource | @Value
/*分配置類*/
/* 先將配置文件讀取出來(lái), 然后用@value為成員變量注入普通屬性*/

@PropertySource("classpath:jdbc.properties")//讀取配置文件
public class DataSourceConfiguration {
    @Value("${jdbc.driver}") //  注入普通屬性
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
  1. @Bean
@Bean(name="dataSource")//spring會(huì)將當(dāng)前方法的返回值,以指定名稱存儲(chǔ)到spring容器中
public DataSource getDataSource() throws PropertyVetoException { 
    ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
    dataSource.setDriverClass(driver);
    dataSource.setJdbcUrl(url);
    dataSource.setUser(username);
    dataSource.setPassword(password);
    return dataSource;
} 
  1. 測(cè)試加載核心配置類,創(chuàng)建spring容器
@Test
public void testAnnoConfiguration() throws Exception {
    //使用AnnotationConfigApplicationContext 加載
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);    
    UserService userService = (UserService)    
    applicationContext.getBean("userService");
    userService.save();
    DataSource dataSource = (DataSource) 
    applicationContext.getBean("dataSource");
    Connection connection = dataSource.getConnection(); 
    System.out.println(connection);
    }

四,Spring整合Junit測(cè)試

4.1 原始Junit測(cè)試 spring問(wèn)題

在測(cè)試類中,每個(gè)測(cè)試方法都必須書寫,讀取配置文件和獲取spring容器的代碼

 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
 IAccountService as = ac.getBean("accountService",IAccountService.class);

以上代碼作用是獲取容器,沒(méi)有會(huì)報(bào)空指針異常.
所以,需要讓springjunit負(fù)責(zé)創(chuàng)建spring容器,但是需要將配置文件的名稱告訴spring,將需要進(jìn)行測(cè)試的bean知己誒在測(cè)試類中進(jìn)行注入

4.2 Spring集成Junit的步驟:

  1. 導(dǎo)入spring集成Junit的坐標(biāo)
  2. 使用@Runwith注解替換原來(lái)的運(yùn)行期
  3. 使用@ContextConfiguration指定配置文件或配置類
  4. 使用@Autowired注入需要測(cè)試的對(duì)象
  5. 創(chuàng)建測(cè)試方法進(jìn)行測(cè)試

4.3代碼示例:

  1. 導(dǎo)入spring集成Junit的坐標(biāo)
<!--此處需要注意的是,spring5 及以上版本要求 junit 的版本必須是 4.12 及以上-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
  1. 使用@Runwith注解替換原來(lái)的運(yùn)行期
@RunWith(SpringJUnit4ClassRunner.class)//記憶
public class SpringJunitTest {
}
  1. 使用@ContextConfiguration指定配置文件或配置類
@RunWith(SpringJUnit4ClassRunner.class)


//加載spring核心配置文件
//@ContextConfiguration(value = {"classpath:applicationContext.xml"})
//加載spring核心配置類
@ContextConfiguration(classes = {SpringConfiguration.class})//告訴配置類位置
public class SpringJunitTest {
}
  1. 使用@Autowired注入需要測(cè)試的對(duì)象
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
    @Autowired//直接進(jìn)行注入
    private UserService userService;
}
  1. 創(chuàng)建測(cè)試方法進(jìn)行測(cè)試
/*搭建好測(cè)試以后 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class}) 
public class SpringJunitTest {
    @Autowired
    private UserService userService;
    @Test
    public void testUserService(){
     userService.save();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容