springMvc的注解注⼊⽅式
最近在看springMvc的源码,看到了该框架的注⼊注解的部分觉的有点吃⼒,可能还是对注解的⽅⾯的知识还认识的不够深刻,所以特意去学习注解⽅⾯的知识。由于本⼈也是抱着学习的态度来阅读源码,若⽂章在表述和代码⽅⾯如有不妥之处,欢迎批评指正。留下你的脚印,欢迎评论!希望能互相学习。
1,⾸先定义三个常⽤的注解Service,Autowired,Contrller;(主要的解释都在代码中有,在这⾥就不多陈述)
Service:
package com.lishun.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*Description:
* @Target:指定注解的使⽤范围(指的是,在哪些类型可以使⽤该注解:Service注解只能在类,接⼝(包括注解类型)或enum等使⽤)
* 可选值:
* 可选的值在枚举类 ElemenetType 中,包括:
ElemenetType.CONSTRUCTOR 构造器声明
ElemenetType.FIELD 域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE 局部变量声明
ElemenetType.ANNOTATION_TYPE 作⽤于注解量声明
ElemenetType.METHOD ⽅法声明
ElemenetType.PACKAGE 包声明
ElemenetType.PARAMETER 参数声明
ElemenetType.TYPE 类,接⼝(包括注解类型)或enum声明
* */
@Target(ElementType.TYPE)
/*Description:
* @Retention :表⽰在什么级别保存该注解信息
* 可选的参数值在枚举类型 RetentionPolicy 中,包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃
RetentionPolicy.CLASS 注解在class⽂件中可⽤,但会被VM丢弃
RetentionPolicy.RUNTIME VM将在运⾏期也保留注释,因此可以通过反射机制读取注解的信息。
* */
@Retention(RetentionPolicy.RUNTIME)
/*@Documented 将此注解包含在 javadoc 中,它代表着此注解会被javadoc⼯具提取成⽂档。
* 在doc⽂档中的内容会因为此注解的信息内容不同⽽不同。相当与@see,@param 等。
* */
@Documented
public @interface Service {
/* @interface⽤来声明⼀个注解,其中的每⼀个⽅法实际上是声明了⼀个配置参数。
* ⽅法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。
* 可以通过default来声明参数的默认值。
*/
String value() default "this is service annotation";
}
Autowired:
package com.lishun.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
public String value() default "no description";
}
Contrller:
package com.lishun.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Contrller {
String value() default "this is contrller annotation";
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------2:javaBean数据池-BeanFactory:主要存放含有注解的类;
package com.lishun.factory;
import java.util.HashMap;
import java.util.Map;
/**
* Description:存放所有bean的数据池
* @author lishun
* @since 2015-09-10
*/
public class BeanFactory {
private static Map<String, Object> map = new HashMap<String, Object>();
public static void addBean(String beanName, Object bean) {
map.put(beanName, bean);
}
public static Object getBean(String beanName) throws Exception {
Object o = (beanName);
if (o != null) {
return o;
} else {
throw new Exception("未注⼊的类型:" + beanName);
}
}
public static Boolean containsBean(String beanName){
ainsKey(beanName);
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3:编写处理注解的核⼼代码(这⾥涉及的主要知识是反射,如果反射知识不够熟练的话建议先学习反射⽅⾯的知识),主要涉及的两个类是注
解驱动(AnnotationDriven)和注解扫描类(PackUtils-这个类主要的是扫描包名下所有的类(如com.lishun,就是扫描该包下所有的类),代码主要是来⾃⽹络)
AnnotationDriven:
package com.lishun.utils;
import java.lang.annotation.Annotation;
import flect.Field;
import java.util.List;
import com.lishun.Annotation.Autowired;
import com.lishun.Annotation.Contrller;
import com.lishun.Annotation.Service;
import com.lishun.factory.BeanFactory;
/**
* Description:注⼊驱动类,所有的注解注⼊都在这⾥实现(这⾥只实现了通过类型来注⼊值,其他⽅式没实现,其实代码都是差不多了,有兴趣的可以⾃⾏脑补)
* @author lishun
*
*/
public class AnnotationDriven {
public static void annotationDriven(String packName) throws Exception {
//注⼊Service和Contrller
List<Class<?>> classSaveServicePaths = PackUtils
.getClassListByAnnotation(packName, Service.class);
List<Class<?>> classSaveContrllerPaths = PackUtils
.getClassListByAnnotation(packName, Contrller.class);
saveBean(classSaveServicePaths);
saveBean(classSaveContrllerPaths);
//注⼊Autowired
List<Class<?>> classInjectPaths = ClassListByAnnotation(
packName, Autowired.class);
inject(classInjectPaths);
}
private static void saveBean(List<Class<?>> classSavePaths)
throws InstantiationException, IllegalAccessException {
for (Class<?> classPath : classSavePaths) {
try {
Class c = Class.Name());
Object o = c.newInstance();
//扫描的到的含有注解的类实例化后保存在池中
BeanFactory.Name(), o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private static void inject(List<Class<?>> classInjectPaths) throws Exception {
Object o = null;
for (Class<?> classInjectPath : classInjectPaths) {
Class c = Class.Name());
//判断存放bean的池中是否存在该bean
if (Name())) {
o = Name());
} else {
o = c.newInstance();
}
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
Annotation[] annotations = Annotations();
for (Annotation annotation : annotations) {
/
/ 判断是否是通过类型注解注⼊
if (annotation instanceof Autowired) {
Class classField = Type();
Object clazz = BeanFactory
.Name());
field.set(o, clazz);
BeanFactory.Name(), o);
}
}
}
}
}
}
PackUtils:
package com.lishun.utils;
import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import flect.Field;
import java.JarURLConnection;
import java.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Description:扫描指定包⼯具类的注解
* @author lishun
* @since 2015-09-10
*/
public class PackUtils {
public static List<Class<?>> getClassList(String packageName, boolean isRecursive) {
List<Class<?>> classList = new ArrayList<Class<?>>();
try {
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().placeAll("\\.", "/"));            while (urls.hasMoreElements()) {
URL url = Element();
if (url != null) {
String protocol = Protocol();
if (protocol.equals("file")) {
String packagePath = Path();
addClass(classList, packagePath, packageName, isRecursive);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = JarFile();
Enumeration<JarEntry> jarEntries = ies();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = Element();
String jarEntryName = Name();
if (dsWith(".class")) {
String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
if (isRecursive || className.substring(0, className.lastIndexOf(".")).equals(packageName)) {
classList.add(Class.forName(className));
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return classList;
}
// 获取指定包名下的所有类(可根据注解进⾏过滤)
public static List<Class<?>> getClassListByAnnotation(String packageName, Class<? extends Annotation> annotationClass) {
List<Class<?>> classList = new ArrayList<Class<?>>();
try {
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().placeAll("\\.", "/"));            while (urls.hasMoreElements()) {
URL url = Element();
if (url != null) {
String protocol = Protocol();
if (protocol.equals("file")) {
String packagePath = Path();
addClassByAnnotation(classList, packagePath, packageName, annotationClass);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = JarFile();
Enumeration<JarEntry> jarEntries = ies();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = Element();
String jarEntryName = Name();
if (dsWith(".class")) {
String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
Class<?> cls = Class.forName(className);
if (cls.isAnnotationPresent(annotationClass)) {
classList.add(cls);
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return classList;
}
private static void addClass(List<Class<?>> classList, String packagePath, String packageName, boolean isRecursive) {
try {
File[] files = getClassFiles(packagePath);
if (files != null) {
for (File file : files) {
String fileName = Name();
if (file.isFile()) {
String className = getClassName(packageName, fileName);
classList.add(Class.forName(className));
} else {
if (isRecursive) {
String subPackagePath = getSubPackagePath(packagePath, fileName);
String subPackageName = getSubPackageName(packageName, fileName);
addClass(classList, subPackagePath, subPackageName, isRecursive);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static File[] getClassFiles(String packagePath) {
return new File(packagePath).listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return (file.isFile() && Name().endsWith(".class")) || file.isDirectory();
}
});
}
springmvc面试题常用注解private static String getClassName(String packageName, String fileName) {
String className = fileName.substring(0, fileName.lastIndexOf("."));
if (!packageName.equals("")) {
className = packageName + "." + className;
}
return className;
}
private static String getSubPackagePath(String packagePath, String filePath) {
String subPackagePath = filePath;
if (!packagePath.equals("")) {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。