文章目录
- 前言
- 一、回顾注解
- 1、注解怎么定义
- 2、注解怎么使用
- 3、通过反射机制怎么读取注解
- 二、Spring IoC注解式开发原理
- 1、扫描程序
- 2、通过反射机制解析注解
- 3、实例化对象
- 三、声明Bean的注解
前言
注解的存在主要是为了简化XML的配置
一、回顾注解
1、注解怎么定义
定义一个注解Component
@Target()//标注注解的注解 叫做元注解。
@Target注解用来修饰@Component可以出现的位置
@Target(value = {ElementType.TYPE,ElementType.FIELD}):用来表示@Component注解可以出现在类上,属性上。
使用某个注解的时候,如果注解的属性名是value的话,value可以省略
即:@Target({ElementType.TYPE,ElementType.FIELD})
使用某个注解的时候,如果注解的属性值是数组,并且数组中只有一个元素,大括号可以省略。
即:@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
也是一个元注解,用来标注@Component注解最终保留在class文件中,并且可以被反射机制读取。
Override源文件
@Retention(RetentionPolicy.SOURCE) 也就是说@Override这个注解只保留在源文件当中,当这个文件编译生成class文件之后,@Override这个注解就没了
注解的属性
//定义注解的属性
//String是属性类型
//value是属性名
String value();
//其他的属性
//String是属性类型
//name是属性名
//String name();
//数组属性
//String[] 是属性类型
//names是属性名
//String[] names();
完整的代码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value();
}
2、注解怎么使用
@Component(属性名=属性值,属性名=属性值,属性名=属性值……)
创建一个User类使用@Component注解
//@Component(value = "UserBean")
//如果属性名是value ,value可以省略
@Component("UserBean")
public class User {
}
3、通过反射机制怎么读取注解
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception {
//通过反射机制读取注解
//1、获取类
Class<?> clazz = Class.forName("com.powernode.bean.User");
//2、获取类上的注解
//2.1、判断类上有没有这个注解
if(clazz.isAnnotationPresent(Component.class)){
//2.2、获取注解
Component annotation = clazz.getAnnotation(Component.class);
//2.3、访问注解的属性
System.out.println(annotation.value());
}
}
}
运行结果:
二、Spring IoC注解式开发原理
需求:目前只知道一个包的名字,扫描这个包下所有的类,当这个类上有@Component注解的时候,实例化该对象,然后放入Map集合当中
1、扫描程序
扫描程序:
1、先把目录改为路径
String packageName = “com.powernode.bean”;
String packagePath = packageName.replaceAll(“\.”,“/”);
2、获取绝对路径
com是在类的根路径下的一个目录
URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
String path = url.getPath();
3、获取绝对路径下的所有文件
File file = new File(path);
File[] files = file.listFiles();
Arrays.stream(files).forEach(f->{
System.out.println(f.getName());
});
System.out.println(f.getName().split(“\.”)[0]);
4、拼接类名
String className = packageName + “.” + f.getName().split(“\.”)[0];
2、通过反射机制解析注解
通过反射机制解析注解:
1.3通过反射机制读取注解
3、实例化对象
实例化对象
Object obj = aClass.newInstance();
Vip类中没有@Component注解,所以没有创建对象
完整代码:
public class ComponentScan {
public static void main(String[] args) throws Exception{
String packageName = "com.powernode.bean";
//开始写扫描程序
//先把目录改为路径。 这个.在正则表达式中表示任意字符,
//在正则表达式中怎么表示一个普通的“.” 使用"\." 在Java语言中“\\.”
String packagePath = packageName.replaceAll("\\.","/");
//System.out.println(packagePath);
//com是在类的根路径下的一个目录
URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
String path = url.getPath();
//System.out.println(path);
File file = new File(path);
File[] files = file.listFiles();
Arrays.stream(files).forEach(f->{
try {
//System.out.println(f.getName());
//System.out.println(f.getName().split("\\.")[0]);
String className = packageName + "." + f.getName().split("\\.")[0];
Class<?> aClass = Class.forName(className);
if (aClass.isAnnotationPresent(Component.class)) {
//获取注解
Component annotation = aClass.getAnnotation(Component.class);
String id = annotation.value();
//有这个注解的都要创建对象
Object obj = aClass.newInstance();
System.out.println(obj);
}
}catch (Exception e){
e.printStackTrace();
}
});
}
}
三、声明Bean的注解
负责声明Bean的注解,常见的包括四个:
- @Component
- @Controller
- @Service
- @Repository
@Component源码
@Controller源码
是Component是别名
@Service
是Component是别名
@Repository
是Component是别名
是为了增强程序的可读性,建议
持久层(Dao)用@Repository
业务层(Service)用@Service
表示层(Web)用@Controller