本節主要通過一個自定義註解瞭解註解是什麼,然後簡要介紹下spring註解分類和作用,最後簡要概括一下web spring容器初始化過程;
1、自定義Annotation_my註解
@Target({ElementType.METHOD,ElementType.TYPE})
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation_my {
String name() default "張三";//defalt 表示默認值
String say() default "hello world";
int age() default 21;
}
上面是按照定義規範自定義一個註解接口,@Annotation_my,你也可以把註解理解爲一個接口,其實他就是一個註釋作用;然後定義person接口
public interface Person {
public void name();
public void say();
public void age();
}
實現接口(student)
@Annotation_my
@SuppressWarnings("unused")
public class Student implements Person {
private String name;
@Override
@Annotation_my(name="流氓公子") //賦值給name 默認的爲張三
//在定義註解時沒有給定默認值時,在此處必須name賦初值
public void name() {
}
@Override
@Annotation_my(say=" hello world !")
public void say() {
}
@Override
@Annotation_my(age=20)
public void age() {
}
}
這裏使用了上面自定義註解,在類外部使用,相當於@Component
,然後方法上面定義的註解,相當於方法的註解;最後我們來使用test類測試一下效果,如下:
public class Test {
Annotation[] annotation = null;
public static void main(String[] args) throws ClassNotFoundException {
new Test().getAnnotation();
}
public void getAnnotation() throws ClassNotFoundException{
Class<?> stu = Class.forName("com.qzx.web.anotation.Student");//靜態加載類
boolean isEmpty = stu.isAnnotationPresent(com.qzx.web.anotation.Annotation_my.class);//判斷stu是不是使用了我們剛纔定義的註解接口
if(isEmpty){
annotation = stu.getAnnotations();//獲取註解接口中的
for(Annotation a:annotation){
Annotation_my my = (Annotation_my)a;//強制轉換成Annotation_my類型
System.out.println(stu+":\n"+my.name()+" say: "+my.say()+" my age: "+my.age());
}
}
Method[] method = stu.getMethods();//
System.out.println("Method");
for(Method m:method){
boolean ismEmpty = m.isAnnotationPresent(com.qzx.web.anotation.Annotation_my.class);
if(ismEmpty){
Annotation[] aa = m.getAnnotations();
for(Annotation a:aa){
Annotation_my an = (Annotation_my)a;
System.out.println(m+":\n"+an.name()+" say: "+an.say()+" my age: "+an.age());
}
}
}
//get Fields by force
System.out.println("get Fileds by force !");
Field[] field = stu.getDeclaredFields();
for(Field f:field){
f.setAccessible(true);
System.out.println(f.getName());
}
System.out.println("get methods in interfaces !");
Class<?> interfaces[] = stu.getInterfaces();
for(Class<?> c:interfaces){
Method[] imethod = c.getMethods();
for(Method m:imethod){
System.out.println(m.getName());
}
}
}
}
通過測試可以知道,註解其實就是註釋的作用,annotation = stu.getAnnotations();通過註釋(綁定到類或方法上),可以給當前對象定義一系列初始操作,比如定義類名稱,其他屬性等;這樣定義好後,spring容器掃描類時候,就能通過註解找到不同定義類型的類,然後進行初始化對象等操作。
2、下面介紹一下spring經常使用的註解
通用類註解 @component,業務層註解@Service,數據訪問層@Reposity ,controller控制器層@Controller,事務@Transaction,相當於xml配置時候的class;
xml配置的id名稱,也就是對象id,到時候對象工廠可以通過BeanFactory
bf = (BeanFactory) reg;@Autowired
或@Resource
對類內部成員屬性進行註解,相當於xml配置的property。使用時候根據情況,可以設置name值,比如@Component("boss"),因爲初始化時默認類是singleton的,這個boss相當於
Object o = bf.getBean("boss
")來找到對象。
3、springmvc初始化過程
tomcat容器爲例,當啓動web服務時候,初始化spring容器,web.xml中兩個地方配置;一個是監聽,一個是dispatcher,如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
和 <servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
web加載配置文件,首先初始化spring監聽服務,讀取beans.xml配置文件,該文件一般配置有數據源、SqlSessionFactory、事務和bean等,按照順序加載,當讀取到 <context:component-scan base-package ="com" />配置時候,打開spring掃描操作,容器會讀取com目錄及子目錄,掃描含有@註解標誌的class文件,掃描是按照類目遞歸進行:比如,掃描com.controller目錄的一個userAction類時,上面含有@Controller註解,beanfactory裝配該類實例(初始化就是生成beanDefinition的實例,BeanDefinition實例是用來描述Bean結構,一般還沒有實例化bean)將beanDefinition實例放入Bean工廠,接着掃描類文件中含有@註解的屬性,比如@AutoWire或@Resource的屬性,一般是service,裝配該類,放入工廠;如此反覆進行,裝配所有類文件。具體過程可以參考https://my.oschina.net/HeliosFly/blog/203149這篇文章。
至於DispatcherServlet這個配置,就是映射控制器中的方法、url路徑信息等,比如@RequestMapping("/index.do"),裝配userAction--methodName--url(index.do)。這樣映射後,當訪問http方法時候,就能找到路徑,然後就可以調用方法了。這些只是我大致理解,裏面有些知識點也不是很清晰,可以自己去查看相關資料,推薦https://my.oschina.net/HeliosFly/blog/203149