JavaEE學習日誌(八十九): spring註解開發詳解

JavaEE學習日誌持續更新----> 必看!JavaEE學習路線(文章總彙)

Spring註解開發

註解開發入門

1、引入依賴
2、配置文件

  • 頭文件增加命名空間和約束
  • 開啓註解
 <context:component-scan base-package="包名"></context:component-scan>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
">
    <!--
        開啓註解,指定掃描的包:context:component-scan
        引入context名稱空間,引入約束

        base-package:指定要掃描的包,掃描的是包和其子包
    -->
    <context:component-scan base-package="com.itheima"></context:component-scan>
</beans>

3、在需要創建的類上添加註解@Component

package com.itheima.dao.impl;

import com.itheima.dao.UserDao;
import org.springframework.stereotype.Component;

@Component
public class UserDaoImpl implements UserDao {
}

4、測試

@Test
    public void test(){
        //創建容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //獲取對象
        UserDao userDao = ac.getBean(UserDao.class);
        System.out.println(userDao);
    }

Component註解

@Component標誌在類上,不能用在方法上
作用:只要掃描了包,就會創建對象

1、衍生了三個子註解

  • @Controller一般用於web層
  • @Service一般用於業務層
  • @Repository一般用於持久層

作用:三個的作用和@Component都是一樣的,但最好別混用。

2、@Component中有個屬性value=""
可以用於指定名字,默認的名稱是簡單類名首字母小寫
(UserServiceImpl->userServiceImpl)

@Component("userService")

相當於xml中

<bean id="userService" class="全限類名"></bean>

自動注入@Autowired

如果想在UserService中調用UserDao,則只需要加上@Autowired註解即可。

可以標記在屬性或set方法上,如果標記在屬性上,可以沒有set方法

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    UserDao userDao;

    public void print(){
        userDao.print();
    }
}

特點:自動按照類型注入
流程:當屬性或方法(set方法)標記了@Autowired,那麼會自動在容器中查找該屬性類型的對象,如果有且只有一個,則注入。

注意:如果有兩個userDao的實現類,則會報錯。
解決方法:
一、在@Autowired下配置上需要注入的名稱,使用註解@Qualifier

@Qualifier("userDaoImpl2")
@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier("userDaoImpl2")
    UserDao userDao;

    public void print(){
        userDao.print();
    }
}

二、根據屬性名注入

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    UserDao userDaoImpl2;

    public void print(){
        userDaoImpl2.print();
    }
}

自動注入@Resource

如果沒有@Resource註解,則寫入依賴

<dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.1</version>
        </dependency>

流程:當屬性或方法(set方法)標記了@Resource

  • 按照名稱查找:會自動按照名稱注入,如果指定了名稱,則按照名稱注入;如果沒有指定名字,則按照屬性名注入。
  • 按照類型查找:如果名稱沒有找到,則按照類型注入;類型有多個則拋出異常

按照指定的名稱注入

@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource(name="userDaoImpl2")
    UserDao userDao;

    public void print(){
        userDao.print();
    }
}

按照屬性名注入

@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource
    UserDao userDaoImpl2;

    public void print(){
        userDaoImpl2.print();
    }
}

按照類型注入(屬性名找不到對應的類時):如果有多個則報異常

@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource
    UserDao userDao;

    public void print(){
        userDao.print();
    }
}

@Autowired@Resource區別
@Autowired

  • 默認按照類型注入,如果類型有多個,則按照名稱注入
  • spring提供

@Resource

  • 默認按照名稱注入,如果名稱沒有找到,則按照類型注入
  • jdk提供

使用半註解半xml改造賬戶CRUD

開啓註解中有兩個屬性
1、context:include-filter:指定包含過濾

  • type="annotation"按照類型過濾
  • expression=""過濾的表達式

在下邊代碼中的含義:只掃描標記了Controller註解的類

2、context:exclude-filter:指定排除過濾

  • type="annotation"按照類型過濾
  • expression=""過濾的表達式

在下邊代碼中的含義:除了Controller註解都會掃描

<!--開啓註解,掃描包-->
    <context:component-scan base-package="com.itheima">
        <!--
            context:include-filter:指定包含過濾
                type="annotation"按照類型過濾
                expression=""過濾的表達式

                只掃描標記了Controller註解的類
        -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--
            context:exclude-filter:指定排除過濾
                type="annotation"按照類型過濾
                expression=""過濾的表達式

                除了Controller註解都會掃描
        -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

配置文件

<?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
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--開啓註解,掃描包-->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!--創建qr對象,需要數據源對象,通過構造方法的參數類型注入-->
    <bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!--創建數據源對象:需要注入四個參數,通過set方法注入-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
</beans>

AccountDaoImpl

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
    @Autowired
    QueryRunner qr;
    //...省略
}

AccountServiceImpl

import com.itheima.dao.AccountDao;
import com.itheima.dao.impl.AccountDaoImpl;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("accountService")
public class AccountServiceImpl implements AccountService {
    //創建容器,使用依賴注入
    @Autowired
    private AccountDao accountDao;
    //...省略
}

測試類

@Test
    public void test(){
        //創建容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //創建service對象
        AccountService accountService = ac.getBean("accountService",AccountService.class);
        List<Account> accountList = accountService.findAll();
        for (Account account : accountList) {
            System.out.println(account);
        }
    }

純註解開發案例

使用純註解改造賬戶CRUD

一、創建SpringConfiguration.java

  1. 標記該類爲配置文件類 @Configuration
  2. 指定註解掃描的包路徑 @ComponentScan({"com.itheima"})
  3. 引入其他配置文件類 @Import({JDBCConfiguration.class})
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * 1、標記該類爲配置文件類    @Configuration
 * 2、指定註解掃描的包路徑    @ComponentScan({"com.itheima"})
 * 3、引入其他配置文件類      @Import({JDBCConfiguration.class})
 *
 *
 */
@Configuration
@ComponentScan({"com.itheima"})
@Import({JDBCConfiguration.class})
public class SpringConfiguration {
}

二、創建JDBCConfiguration.java

  • @Configuration:可以省略
  • @Bean("name")用在方法上,用來指定方法創建的對象存到容器中,一般用於別人的類,相當於<bean>標籤
    "name"就是在容器中的名稱
package com.itheima.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * 配置持久層的對象
 * @Configuration:可以省略
 * @Bean("name"):用在方法上,用來指定方法創建的對象存到容器中
 *          "name"就是在容器中的名稱
 *
 */
@Configuration
public class JDBCConfiguration {
    @Bean("queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        //需要通過構造方法,注入dataSource
        QueryRunner queryRunner = new QueryRunner(dataSource);
        return queryRunner;
    }
    /**
     * 創建數據源對象:dataSource
     * @return
     */
    @Bean("dataSource")
    public DataSource createDataSource(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        try {
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return dataSource;
    }
}

三、測試
注意:使用ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);

 @Test
    public void test(){
        //創建容器
//        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //純註解創建容器對象
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);

        //創建service對象
        AccountService accountService = ac.getBean("accountService",AccountService.class);
        List<Account> accountList = accountService.findAll();
        for (Account account : accountList) {
            System.out.println(account);
        }
    }

改造純註解

改造一:數據庫的一些屬性寫死了,把他們放到配置文件中

  • @PropertySource({"jdbc.properties"})引入properties文件
  • @Value給屬性賦值
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
package com.itheima.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * 配置持久層的對象
 * @Configuration:可以省略
 * @Bean("name"):用在方法上,用來指定方法創建的對象存到容器中
 *          "name"就是在容器中的名稱
 *
 */
@Configuration
@PropertySource({"jdbc.properties"})
public class JDBCConfiguration {
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.driver}")
    private String driverClass;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean("queryRunner")
    public QueryRunner createQueryRunner(DataSource dataSource){
        //需要通過構造方法,注入dataSource
        QueryRunner queryRunner = new QueryRunner(dataSource);
        return queryRunner;
    }
    /**
     * 創建數據源對象:dataSource
     * @return
     */
    @Bean("dataSource")
    public DataSource createDataSource(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        try {
            dataSource.setDriverClass(driverClass);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return dataSource;
    }
}

改造二:創建的對象默認是單例模式,將他改成多例模式

在類上添加註解@Scope("prototype")

@Repository("accountDao")
@Scope("prototype")
public class AccountDaoImpl implements AccountDao 

改造三:可以添加對象的初始化和銷燬方法(一般不用)

  • @PostConstruct:相當於bean標籤的屬性init-method,指定初始化方法
  • @PreDestroy:相當於bean標籤的屬性:destroy-method,指定對象的銷燬方法

xml引入外部文件

一、xml中引入xml

關鍵代碼

<import resource="classpath:applicationContext-dao.xml"></import>

applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--引入外部屬性文件-->
    <import resource="classpath:applicationContext-dao.xml"></import>
    <!--創建AccountService對象:需要AccountDao對象,依賴注入dao對象-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

</beans>

applicationContext-dao.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--創建AccountDao對象,需要qr-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <!--通過set方法注入qr-->
        <property name="qr" ref="qr"></property>
    </bean>
    <!--創建qr對象,需要數據源對象,通過構造方法的參數類型注入-->
    <bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!--創建數據源對象:需要注入四個參數,通過set方法注入-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
</beans>

二、xml中引入properties文件

關鍵代碼

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

applicationContext-dap.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 http://www.springframework.org/schema/context/spring-context.xsd">
    <!--創建AccountDao對象,需要qr-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <!--通過set方法注入qr-->
        <property name="qr" ref="qr"></property>
    </bean>
    <!--創建qr對象,需要數據源對象,通過構造方法的參數類型注入-->
    <bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!--創建數據源對象:需要注入四個參數,通過set方法注入-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--引入外部屬性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
</beans>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章