學習Spring(八) -- Spring使用註解配置bean

使用註解配置Beanjava

    第一件要作的事情就是,添加spring-aop.jar包到項目中。spring

    Spring推薦使用4個註解來描述類:express

  1. @Component:組件less

  2. @Repository:持久化層ide

  3. @Service:業務層函數

  4. @Controller:控制器層測試

    建立一個user的持久層、業務層和控制器層,並使用註解進行依賴注入:ui

@Component
public class TestObject { } // 創建一個組件。
public interface UserRepository {
    void save();
} // 創建一個持久化層的接口。
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    @Override
    public void save() {
        System.out.println("User Repository Save...");
    }
}
// 持久化接口的實現類,指定@Repoitory註解。

    @Repository("userRepository"):@Repository能夠添加一個Name參數,意思<bean id="..." />同樣。spa

@Service
public class UserService {
    public void add() {
        System.out.println("user service add...");
    }
} // 業務層的代碼。
@Controller
public class UserController {
    public void execute(){
        System.out.println("user controller execute...");
    }
} // 控制器層代碼。

    使用context標籤來添加配置掃描器:.net

<?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:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/spring-util-4.2.xsd 
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
    <!-- 指定spring IOC掃描的package -->
    <context:component-scan base-package="cn.net.bysoft.lesson6">
    </context:component-scan>
</beans>

    context:component-scan的base-package屬性用來告訴掃描器,掃描哪一個包裏的文件,能夠使用*通配符:

<context:component-scan base-package="cn.net.bysoft.*">

    編寫一段測試代碼:

    getBean的參數,默認爲類的全名,但首字母小寫。但是若是在註解中寫了別名,就須要用別名來getBean,好比上面的userRepositoryImpl類。

    context:component-scan還能夠對掃描的包進行細緻的過濾。


    能夠在元素中加入context:exclude-filter和context:include-filter,前者是排除要掃描的包中的某某某,後者是包含要掃描的包中的某某某,作一個例子使用一下。

    上面的4個對象都在cn.net.bysoft.lesson6這個包中,但若是想排除掉TestObject該怎麼作呢?以下:

<context:exclude-filter type="annotation" 
                        expression="org.springframework.stereotype.Component"/>

    上面這段代碼表明移除全部的@Component註解。

    若是有多個類被@Component註解所描述,不想一次都排除掉,能夠修改type="assignable",在expression處填寫全類名:

<context:exclude-filter type="assignable" expression="cn.net.bysoft.lesson6.TestObject"/>

    包含的用法與排除是同樣的,可是有一個細節須要注意,就是context:component-scan元素的use-default-filters屬性,這個屬性是默認的掃描器過濾器是否啓動,模式是等於true的,若是須要用context:include-filter,須要將這個屬性設置爲false:

<context:component-scan base-package="cn.net.bysoft.lesson6" use-default-filters="false">
    <context:include-filter type="assignable" expression="cn.net.bysoft.lesson6.TestObject"/>
</context:component-scan>

使用註解配置Bean之間的依賴注入

    一般,咱們作一個對象的CRUD,都是在Controller層調用Service層的方法,在Service層調用Dao層的方法,那麼模擬這個作法,對上面的代碼進行修改,模擬類之間的引用:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    
    public void execute(){
        System.out.println("user controller execute...");
        userService.add();
    }
}

    設置bean以前的引用,使用@Autowired(自動裝配)註解進行描述,Spring會去匹配類型兼容的bean,能夠用來描述字段、構造函數和setter方法。把接下來的代碼補全:

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public void add() {
        System.out.println("user service add...");
        userRepository.save();
    }
}
package cn.net.bysoft.lesson6;

import org.springframework.stereotype.Repository;

@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {

    @Override
    public void save() {
        System.out.println("User Repository Save...");
    }
}

    結果顯示正常。

    其中Controller類、Service類和Repository類都被註解描述了,可是若是用@Autowired註解去描述沒有被註解描述的類是會報錯的,須要在@Autowired中設置required=false。

    咱們把以前的TestObject類的註解去掉:

package cn.net.bysoft.lesson6;

public class TestObject { }

    而後在Controller類中使用它,運行程序:

@Controller
public class UserController {
    @Autowired
    private UserService userServicea;
    
    @Autowired()
    private TestObject testObject;
    
    public void execute(){
        System.out.println("user controller execute...");
        userServicea.add();
        System.out.println("打印testObject: " + testObject);
    }
}


    報錯,不能自動裝載字段,修改一下注釋:

@Autowired(required=false)
private TestObject testObject;


    再也不報錯了,容許描述的字段爲null。

    下面的問題,若是在註解中,一個接口被多個類實現,那麼自動裝配應該去裝配哪一個類呢,好比上面的代碼中,咱們的UserRepository是一個Interface,被UserRepositoryImpl實現,如今,我在建立一個類實現UserRepository:

@Repository()
public class UserRedisRepositoryImpl implements UserRepository {

    @Override
    public void save() {
        System.out.println("User Redis Repository Save...");
    }
}

    而後刪除掉UserRepositoryImpl的別名,把@Repository("userRepository")改爲@Repository:

@Repository
public class UserRepositoryImpl implements UserRepository {

    @Override
    public void save() {
        System.out.println("User Repository Save...");
    }

}

    在進行測試,結果發生了異常:

    有幾種方式解決,第一個是爲其中的某一個類設置@Repository("userRepository"),還能夠使用@Qualifier("userRedisRepositoryImpl")來在聲明字段時裝配指定類型的

@Service
public class UserService {
    @Autowired
    @Qualifier("userRedisRepositoryImpl")
    private UserRepository userRepository;

    public void add() {
        System.out.println("user service add...");
        userRepository.save();
    }
}


泛型的依賴注入

package cn.net.bysoft.lesson6;

import org.springframework.beans.factory.annotation.Autowired;

public class BaseService<T> {
    @Autowired
    protected BaseRepository<T> baseRepository;
    
    public void add(T t) {
        System.out.println("add...");
        baseRepository.save(t);
    }
}
package cn.net.bysoft.lesson6;

public class BaseRepository<T> {
    public void save(T t) {
        System.out.println(t.getClass() + " save...");
    }
}
public class Dept {}
public class Role {}
@Service
public class DeptService extends BaseService<Dept> { }
@Repository
public class DeptRepository extends BaseRepository<Dept> { }
@Service
public class RoleServiceextends BaseService<Role> {}
@Repository
public class RoleRepository extends BaseRepository<Role> {}

    先粘貼出來了八個類,第一個類是泛型Service,第二個類是泛型Repository,第三個和第四個類是兩個實體類,第五個第六個是Dept的業務類與持久化類,最後兩個是Role的業務類與持久化類。

    能夠看到,除了兩個Base類以外,與以前的配置是同樣的,關鍵在於Base類的配置。

    Base類不須要對類進行註解,由於它是用來被繼承的,因此由繼承它的子類使用類註解。

    只須要對引用的類進行@Autowired描述便可,測試一下:


    以上,就是使用註解描述bean的基本內容。

相關文章
相關標籤/搜索