使用註解配置Beanjava
第一件要作的事情就是,添加spring-aop.jar包到項目中。spring
Spring推薦使用4個註解來描述類:express
@Component:組件less
@Repository:持久化層ide
@Service:業務層函數
@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的基本內容。