作者:Matzoh | 来源:互联网 | 2023-09-24 14:13
本节主要通过一个自定义注解了解注解是什么,然后简要介绍下spring注解分类和作用,最后简要概括一下webspring容器初始化过程;1、自定义Annotation_my注解@Target({Ele
本节主要通过一个自定义注解了解注解是什么,然后简要介绍下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;@Autowired
或@Resource
对类内部成员属性进行注解,相当于xml配置的property。使用时候根据情况,可以设置name值,比如@Component("boss"),因为初始化时默认类是singleton的,这个boss相当于
xml配置的id名称,也就是对象id,到时候对象工厂可以通过BeanFactory bf = (BeanFactory) reg;
Object o = bf.getBean("boss
")来找到对象。
3、springmvc初始化过程
tomcat容器为例,当启动web服务时候,初始化spring容器,web.xml中两个地方配置;一个是监听,一个是dispatcher,如下:
contextConfigLocation
classpath:beans.xml
org.springframework.web.context.ContextLoaderListener
和
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
web加载配置文件,首先初始化spring监听服务,读取beans.xml配置文件,该文件一般配置有数据源、SqlSessionFactory、事务和bean等,按照顺序加载,当读取到 配置时候,打开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