Spring——使用IoC和DI模擬註冊案例、註解配置IoC和DI

目錄

在這裏插入圖片描述


一、 使用IoC和DI模擬註冊案例(XML配置)

跳轉到目錄

  • 數據庫
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(40) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

使用的一些類和接口
在這裏插入圖片描述

  • 類和接口
// domain包下的User類
@Getter
@Setter
@ToString
public class User {
    private Long id;
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

//--------------------------------------------

// controller包下的UserController類
// 模擬Struct2的Action / SpringMVC的Controller
public class UserController {

    @Setter
    private UserService service;

    public String register(){
        System.out.println("註冊請求");
        service.register(new User("朝陽", 100));
        return "success";
    }
}

//--------------------------------------------

// service包下的UserService接口和實現類
public interface UserService {
    // 註冊
    void register(User u);
}
public class UserServiceImpl implements UserService {

    @Setter
    private UserDao dao;

    public void register(User u) {
        System.out.println("註冊方法");
        dao.save(u);
    }
}

//--------------------------------------------

// dao包下的UserDao接口和實現類
public interface UserDao {
    // 保存用戶信息
    void save(User u);
}
public class UserDaoImpl implements UserDao {

    @Setter
    private DataSource dataSource;

    @SneakyThrows // 偷偷拋出已檢查的異常
    public void save(User u) {
        System.out.println("保存操作");
        @Cleanup // 處理資源關閉
        Connection conn = dataSource.getConnection();
        String sql = "INSERT INTO user(name ,age) VALUES(?,?)";
        @Cleanup
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1, u.getName());
        ps.setInt(2, u.getAge());
        ps.executeUpdate();
    }
}
  • db.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=1111
jdbc.initialSize=2
  • xml文件(重點操作)
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--從classpath的根路徑去加載db.properties文件-->
    <!--<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--配置一個druid的連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="${jdbc.initialSize}"/>
    </bean>

    <!--配置DAO-->
    <bean id="userDao" class="com.sunny._06_register.dao.impl.UserDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置service-->
    <bean id="userService" class="com.sunny._06_register.service.impl.UserServiceImpl">
        <property name="dao" ref="userDao"/>
    </bean>

    <!--配置Action/Controller
        如果使用Struct2的Action,此時bean的作用域應該是多例: scope="prototype"
        如果使用的SpringMVC的Controller, 此時bean的作用域應該是單例的
    -->
    <bean id="userController" class="com.sunny._06_register.controller.UserController">
        <property name="service" ref="userService"/>
    </bean>
</beans>

在這裏插入圖片描述

  • 測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class RegisterTest {

    // @Autowired:表示從Spring IoC容器中根據類型找到對應的bean,並自動注入到某個字段上
    @Autowired
    private UserController uc;

    @Test
    public void test(){
        uc.register();
    }
}
  • 輸出
    在這裏插入圖片描述

二、註解配置IoC和DI

 * 曾經XML的配置:
 *  <bean id="accountService" class="com.sunny.service.impl.AccountServiceImpl"
 *        scope=""  init-method="" destroy-method="">
 *      <property name=""  value="" | ref=""></property>
 *  </bean>
 *
 * 用於創建對象的
 *      他們的作用就和在XML配置文件中編寫一個<bean>標籤實現的功能是一樣的
 *      Component:
 *          作用:用於把當前類對象存入spring容器中
 *          屬性:
 *              value:用於指定bean的id。當我們不寫時,它的默認值是當前類名,且首字母改小寫。
 *      Controller:一般用在表現層
 *      Service:一般用在業務層
 *      Repository:一般用在持久層
 *      以上三個註解他們的作用和屬性與Component是一模一樣。
 *      他們三個是spring框架爲我們提供明確的三層使用的註解,使我們的三層對象更加清晰
 *
 *
 * 用於注入數據的
 *      他們的作用就和在xml配置文件中的bean標籤中寫一個<property>標籤的作用是一樣的
 *      Autowired:
 *          作用:自動按照類型注入。只要容器中有唯一的一個bean對象類型和要注入的變量類型匹配,就可以注入成功
 *                如果ioc容器中沒有任何bean的類型和要注入的變量類型匹配,則報錯。
 *                如果Ioc容器中有多個類型匹配時:
 *          出現位置:
 *              可以是變量上,也可以是方法上
 *          細節:
 *              在使用註解注入時,set方法就不是必須的了。
 *      Qualifier:
 *          作用:在按照類中注入的基礎之上再按照名稱注入。它在給類成員注入時不能單獨使用。但是在給方法參數注入時可以(稍後我們講)
 *          屬性:
 *              value:用於指定注入bean的id。
 *      Resource
 *          作用:直接按照bean的id注入。它可以獨立使用
 *          屬性:
 *              name:用於指定bean的id。
 *      以上三個注入都只能注入其他bean類型的數據,而基本類型和String類型無法使用上述註解實現。
 *      另外,集合類型的注入只能通過XML來實現。
 *
 *      Value
 *          作用:用於注入基本類型和String類型的數據
 *          屬性:
 *              value:用於指定數據的值。它可以使用spring中SpEL(也就是spring的el表達式)
 *                      SpEL的寫法:${表達式}
 *
 * 用於改變作用範圍的
 *      他們的作用就和在bean標籤中使用scope屬性實現的功能是一樣的
 *      Scope
 *          作用:用於指定bean的作用範圍
 *          屬性:
 *              value:指定範圍的取值。常用取值:singleton prototype
 *
 * 和生命週期相關 瞭解
 *      他們的作用就和在bean標籤中使用init-method和destroy-methode的作用是一樣的
 *      PreDestroy
 *          作用:用於指定銷燬方法
 *      PostConstruct
 *          作用:用於指定初始化方法

跳轉到目錄

1、DI註解

跳轉到目錄

1.1、Autowired註解和Qualifier註解

跳轉到目錄
在這裏插入圖片描述
Java類

public class Cat {
}
public class Person {
    //@Autowired
    private Cat c1;

/*  @Autowired
    public void setC1(Cat c1) {
        this.c1 = c1;
    }*/
    @Override
    public String toString() {
        return "Person{" +
                "c1=" + c1 +
                '}';
    }
}

將@Autowired貼在字段或者setter方法上,Spring會自動將該字段所需要的對象(cat對象)找出來並注入到該對象(person)中, 以前還需要在XML中手動將Cat用ref注入到Person對象中;

  • xml配置
    一定要配置DI註解解析器(對DI註解作解釋)
    <context:annotation-config/>
    
<!--DI註解解析器
    在Spring Test中,不用配就可以
    在普通測試中,必須要配;
    開發中一般都要配置!
-->
<context:annotation-config/>

<bean id="cat1" class="com.sunny.di.Cat"/>
<bean id="cat2" class="com.sunny.di.Cat"/>
<bean id="person" class="com.sunny.di.Person"/>
1.2、Resource註解

跳轉到目錄
在這裏插入圖片描述

// 只會去找id爲cat1的Cat對象,如果找不到就直接報錯!
@Resource(name = "cat1")
private Cat c1;

注意: @Autowired@Resource基本上功能一模一樣,開發中兩者選其一即可!
在這裏插入圖片描述

1.3、Value註解

跳轉到目錄
Autowired和Resource註解用於注入對象, Value註解用於注入常量數據(簡單類型數據);

server.properties

server.port=781

Java類

public class ValueBean {
    //@Value("9999")
    @Value("${server.port}")
    private int port;

    @Override
    public String toString() {
        return "ValueBean{" +
                "port=" + port +
                '}';
    }
}

xml文件

    <!--DI註解解析器
        在Spring Test中,不用配就可以
        在普通測試中,必須要配;
        開發中一般都要配置!
    -->
    <context:annotation-config/>

    <!--加載properties文件-->
    <context:property-placeholder location="classpath:db.properties, classpath:server.properties "/>
    
    <bean id="valueBean" class="com.sunny.di.ValueBean"/>

在這裏插入圖片描述
測試類

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class DiTest {

    //@Autowired
    @Resource
    private Person person;

    @Autowired
    private ValueBean valueBean;

    @Test
    public void test(){
        System.out.println(person);
        System.out.println(valueBean);
    }
}

在這裏插入圖片描述

2、IoC註解

跳轉到目錄
bean組件版型:四個組件的功能是相同的,只是用於標註不同類型的組件。

  • @Component泛指組件,當組件不好歸類的時候,我們可以使用這個註解進行標註。
  • @Repository用於標註數據訪問組件, 即DAO組件
  • @Service用於標註業務層組件
  • @Controller用於標註控制層組件(如struts中的Action , SpringMVC的Controller) .

配置IoC註解解析器

 <!--IoC註解解析器-->
 <context:component-scan base-package="com.sunny.ioc"/>

表示去哪些包中及其子包中掃描組件註解

Java類

// XML配置方式: <bean id="myDataSource" class="com.sunny.ioc.MyDataSource"/>
// 註解配置: @Component
@Component("myDataSource") //組件如果不寫value屬性值,此時bean的id默認是類型首字母小寫:myDataSource
public class MyDataSource {
}

xml文件

<!--DI註解解析器-->
<context:annotation-config/>

<!--IoC註解解析器-->
<context:component-scan base-package="com.sunny.ioc"/>

<!--以前使用XML的方式,交給Spring容器來創建MyDataSource對象-->
<!--<bean id="myDataSource" class="com.sunny.ioc.MyDataSource"/>-->

測試類

    @Autowired
    private MyDataSource mds;

    @Test
    public void test(){
        System.out.println(mds);
    }

兩種方式都可以成功創建MyDataSource對象!

3、作用域註解和初始化、銷燬註解

跳轉到目錄

  • 作用域註解使用@Scope註解
  • 初始化註解使用@PostConstruct 用於貼在初始化方法上
  • 銷燬註解使用@PreDestroy 用於貼在銷燬方法上

java類

@Component
//@Scope("prototype") // 默認不寫就是單例的
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class SomeBean {
    public SomeBean() {
        System.out.println("構造SomeBean對象");
    }

    @PreDestroy // 銷燬對象之前執行
    public void close() {
        System.out.println("銷燬方法");
    }

    @PostConstruct // 構建對象之後執行
    public void open() {
        System.out.println("初始化方法");
    }
    public void doWork() {
        System.out.println("工作");
    }
}
    <!--老方式-->
    <!--<bean id="someBean" class="com.sunny.lifecycle.SomeBean"
        init-method="open" destroy-method="open"
    />-->

    <!--配置IoC註解解析器-->
    <context:component-scan base-package="com.sunny.lifecycle"/>

測試類

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class LifeCycleTest {

    @Autowired
    private SomeBean sb1;
    @Autowired
    private SomeBean sb2;

    @Test
    public void test(){
        System.out.println(sb1);
        System.out.println(sb2);
        sb1.doWork();
    }
}

在這裏插入圖片描述

4、 IoC和DI其實是同一個東西

跳轉到目錄

  • IoC: 字面上,更多強調的是Spring容器幫我們創建對象
  • DI: 字面上,Spring不僅幫我們創建對象,還要爲該對象設置依賴的數據

三、 使用IoC和DI模擬註冊案例(註解配置)

跳轉到目錄

  • 數據庫
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(40) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

使用的一些類和接口
在這裏插入圖片描述

  • 類和接口
// domain包下的User類
@Getter
@Setter
@ToString
public class User {
    private Long id;
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

//--------------------------------------------

// controller包下的UserController類
// 模擬Struct2的Action / SpringMVC的Controller
@Controller
public class UserController {
	//@Setter
	@Autowired
    private UserService service;

    public String register(){
        System.out.println("註冊請求");
        service.register(new User("陽仔", 99));
        return "success";
    }
}

//--------------------------------------------

// service包下的UserService接口和實現類
public interface UserService {
    // 註冊
    void register(User u);
}
@Repository
public class UserServiceImpl implements UserService {
	
	//@Setter
    @Autowired // 是按類型去找
    private UserDao dao;

    public void register(User u) {
        System.out.println("註冊方法");
        dao.save(u);
    }
}

//--------------------------------------------

// dao包下的UserDao接口和實現類
public interface UserDao {
    // 保存用戶信息
    void save(User u);
}
@Repository
public class UserDaoImpl implements UserDao {
	//@Setter
    @Autowired
    private DataSource dataSource;

    @SneakyThrows // 偷偷拋出已檢查的異常
    public void save(User u) {
        System.out.println("保存操作");
        @Cleanup // 處理資源關閉
        Connection conn = dataSource.getConnection();
        String sql = "INSERT INTO user(name ,age) VALUES(?,?)";
        @Cleanup
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1, u.getName());
        ps.setInt(2, u.getAge());
        ps.executeUpdate();
    }
}

在這裏插入圖片描述

  • db.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=1111
jdbc.initialSize=2
  • xml文件(重點操作)
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--DI註解解析器-->
    <context:annotation-config/>
    <!--IoC註解解析器
        會自動掃描register的子包
    -->
    <context:component-scan base-package="com.sunny._01_register"/>

    <!--從classpath的根路徑去加載db.properties文件-->

    <context:property-placeholder location="classpath:db.properties, classpath:server.properties "/>
    <!--<context:property-placeholder location="classpath:db.properties" ignore-resource-not-found="true"/>
    <context:property-placeholder location="classpath:server.properties" ignore-resource-not-found="true"/>-->

    <!--配置一個druid的連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="${jdbc.initialSize}"/>
    </bean>
    
</beans>
  • 測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class RegisterTest {

    // @Autowired:表示從Spring IoC容器中根據類型找到對應的bean,並自動注入到某個字段上
    @Autowired
    private UserController uc;

    @Test
    public void test(){
        uc.register();
    }
}
  • 輸出
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章