9 Spring基本註解程式設計
9 Spring基本註解程式設計
環境配置:在進行註解的使用之前我們需要在配置檔案中加入
<context:component-scan base-package="#包的全限命名"/>
開發目錄
1.建立物件相關@Component
基本功能
用於替代配置檔案中的
例如:我們原來建立物件的方式是這個樣子
<bean id="#ID" class="#類名的全限命名"/>
現在只需要在需要建立的類上面加入@Component
@Component
public class User {
xxxx
}
(重要)我們就直接可以在工廠使用類名的首字母小寫作為ID創建出來物件
指定標籤
我們可在括號中給它標註需要的ID例如:
@Component("user1")
我們就把它ID改為了user1
覆蓋標籤
我們覺得不滿意,可以在配置檔案中進行覆蓋處理,但是我們需要讓id和註解的id保持一致,否則,Spring會建立同名不同類的物件,也就起不到覆蓋的作用
例如:我改了上面對應註解的類,並改了建立這個類時的一些屬性
<bean id="user" class="#類名的全限命名" scope="prototype"/>
其他相同功能的註解
和@Component功能一致,但是是為了專門標註執行不同業務的類
- @Controller 標註Controller
- @Repository 標註 DAO
- @Repository 標註 Service
但是在和Mybaits 整合的時候我們不用@Repository 以及@Component
2.@Scope
傳統開發中我們指定何時建立對像,在標籤中指定scope
在註解開發中使用@Scope("prototype")或者@Scope("singleton")都是一樣的
例如:物件將在使用時建立
@Scope("prototype")
public class User {
xxxx
}
3.@Lazy,@PostConstruct,@PreDestroy
推後(延遲)建立物件,在工廠建立時如果沒有指定延遲建立,那麼此物件的無參構造方法和初始化方法都會執行
@Lazy指定這個類是否延遲載入,在使用時載入
@PostConstruct 指定這個方法為初始化方法
@PreDestroy指定這個方法為銷燬方法
例如:
@Lazy(true)
public class UserServiceImpl implements UserService {
//無參構造方法
public UserServiceImpl() {
System.out.println("UserServiceImpl.UserServiceImpl");
}
//初始化方法
@PostConstruct
public void MyinitMehtond(){
System.out.println("UserServiceImpl.MyinitMehtond");
}
//銷燬方法
@PreDestroy
public void MyDestory(){
System.out.println("UserServiceImpl.MyDestory");
}
}
使用了@Lazy(true)那麼在建立工廠時它被稍後使用時載入
例如建立工廠程式碼
public void test2(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-Annotation.xml");
//UserService service= (UserService) context.getBean("userServiceImpl");
}
執行它發現沒任何反應
我們使用它取消使用它的註釋,可以看到這個方法被載入了包括初始化方法
那麼@PreDestroy是在工廠關閉時啟動銷燬方法,銷燬工廠context.close();
可以看到銷燬方法被呼叫
4.注入的相關注解@Autowired,@PropertySource,@Value
自定義型別
@Autowired將為放置位置的變數進行注入
例如:我們有了一個DAO的物件,要使用它的save方法,我們得首先建立他
@Repository
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
System.out.println("UserDAOImpl.save");
}
}
在Service層中呼叫它就得把他建立的物件賦值給對應方法
@Service
public class UserServiceImpl implements UserService {
//宣告的DAO變數
//方式一
private UserDAO userDAO;
public UserDAO getUserDAO() {
System.out.println("UserServiceImpl.getUserDAO");
return userDAO;
}
//提供SET和GET方法
//方式二
//@Autowired
public void setUserDAO(UserDAO userDAO) {
System.out.println("UserServiceImpl.setUserDAO");
this.userDAO = userDAO;
}
//呼叫DAO方法
@Override
public void register() {
System.out.println("UserServiceImpl.register");
userDAO.save();
}
@Override
public void login(String name, String password) {
System.out.println("UserServiceImpl.login");
}
方式一:在成員變數上註解
Spring會自動的通過反射為對應的變數進行注入[推薦方式]
方式二:在set方法上面進行註解
Spring會自動的尋找與之對應的成員變數(也就是上面宣告的DAO變數)的相同型別或者子類
JDK型別
這個方法比較麻煩、
開發步驟:
- 在properties檔案中設定鍵值對
- 在工廠或者註解讀取配置檔案
- 寫註解
-
在properties檔案中設定鍵值對
例如我要為實體類的兩個變數注入兩個值
public class User implements Serializable { private String name; private String password; //為其提供SET/GET方法這裡就不寫出來了,節約篇幅 }
在配置檔案DataBase.properties中如下書寫
JDBC_User=root JDBC_Password=atgxstuSf2e
-
在工廠或者註解讀取配置檔案
在類上使用@PropertySource註解表明配置檔案
@PropertySource("classpath:/DataBase.properties") public class User implements Serializable { private String name; private String password; }
-
寫註解
格式為@Value("${鍵值}")
@PropertySource("classpath:/DataBase.properties") public class User implements Serializable { @Value("${JDBC_User}") private String name; @Value("${JDBC_Password}") private String password; }
注意點:
這個注入方法不能用在靜態成員變數以及不可以注入集合等複雜型別,使用還是比較繁瑣
5.註解掃描
在上面的環境配置配置了Spring需要掃描的包的註解,那麼用起來必須有侷限性,Spring還提供了自定義的對註解掃描的方式
總體來說,Spring為我們提供了兩種自定義註解掃描方式
- 包含形式
- 排除形式
包含形式和排除形式都大同小異
大同在有相同的掃描方法和對掃描方法的配置
- assignable 基於特定型別的方式
- aspectj 基於切入點表示式的方式
- annotation 基於註解的方式
- custom 用於Spring框架底層開發(沒到那個水平)
- regex 基於正則表示式的方式(和切入點表示式比起來肯定切入點表示式好用)
1.排除形式
配置形式
<context:component-scan base-package="#某個包">
<context:exclude-filter type="#掃描方法" expression="#掃描方法的配置"/>
</context:component-scan>
一,assignable
我把org.AnnotationProgramming.Entity.User這個類排除了,不作為掃描的類,所以也就不會被Spring創建出來(事先加入了@Component註解)
<context:exclude-filter type="assignable" expression="org.AnnotationProgramming.Entity.User"/>
測試程式碼:
getBeanDefinitionNames是Spring建立的物件名字
public void test3(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext-Annotation.xml");
String[]strings=context.getBeanDefinitionNames();
for (String string : strings) {
System.out.println("string = " + string);
}
}
執行結果:
可以看到User類並沒有被創建出來說明被排除了
二,aspectj
排除了org.AnnotationProgramming.DAO這個包下的所有類
具體演示就不弄了
<context:exclude-filter type="aspectj" expression="org.AnnotationProgramming.DAO..*"/>
三,annotation
排除了Repository這個註解,需要填寫註解的全限命名
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
四,custom和regex使用頻率極低就不介紹
2.包含屬性
所有的內容和排除一致,只不過掃描的類從排除變為掃描了
3.混合使用
包含和排除屬性可以任意搭配,不過排除之後不可以使用包含,注意選擇邏輯,自由搭配
6.對註解開發的其他注意事項
1.註解配置的類和配置檔案是互通的,也就是說註解中設定的ID在配置檔案中可以使用
2.使用註解的時機:多在自己開發程式時候,也就是自己寫的類,但是在使用其他人提供的類,比如SqlsessionFactoryBean還是得在配置檔案中進行配置,所以開發是混合開發
還有更多高階註解(Spring3以後)在下一篇筆記將會提到,這些都屬於基礎註解,也就是早期Spring提供的註解