spring6-注解式开发 [复制链接]
发表于 2026-2-5 00:51:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
spring框架创建bean就是使用反射机制

反射机制的代码如下:
  1. public static void main(String[] args) throws Exception {
  2.     System.out.println("Hello, World!");
  3.     // 使用反射机制调用方法
  4.     // 获取类
  5.     Class<?> clazz = Class.forName("com.ali.bean2.SomeService");
  6.     // 获取方法
  7.     Method method = clazz.getMethod("doSomething", String.class, int.class);
  8.     // 获取对象
  9.     Object obj = clazz.newInstance();
  10.     // 方法调用
  11.     // obj: 哪个对象调用这个方法
  12.     // "hello", 42: 方法参数
  13.     // hello: 方法的返回值
  14.     Object hello = method.invoke(obj, "hello", 42);
  15. }
复制代码
spring IoC注解式开发

注解告急是为了简化xml设置。
注解怎么界说

新建Java Class 时选择Annoation 范例的文件,如许就创建了一个新的注解
  1. // 自定义注解
  2. // @Target 标注注解的注解,叫做元注解
  3. // ElementType.TYPE: 表示可以标注在类上
  4. // ElementType.FIELD: 表示可以标注在属性上
  5. // 使用某个注解的时候,如果注解的属性名是value,可以省略属性名
  6. // 使用某个注解的时候,如果注解的属性值是数组,并且数组中只有一个值,可以省略大括号
  7. @Target(value = {ElementType.TYPE,ElementType.FIELD})
  8. // @Retention 标注注解的生命周期,叫做元注解,表示最终保留在class文件中,并且可以被反射机制读取
  9. // RetentionPolicy.SOURCE: 注解只在源码中存在,编译成字节码后就不存在了
  10. // RetentionPolicy.CLASS: 注解在源码和字节码中都存在,运行时不存在(默认值),也就是不能被反射机制读取
  11. // RetentionPolicy.RUNTIME: 注解在源码、字节码和运行时都存在
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface Component {
  14.     String value();
  15. }
复制代码
怎么通过反射机制读取注解

假设user类被注解@Component修饰
  1. @Component("userBean")
  2. public class User {
  3. }
复制代码
  1. public static void main(String[] args) throws Exception {
  2.     // 使用反射机制读取注解
  3.     // 获取类
  4.     Class<?> userClazz = Class.forName("com.ali.component.User");
  5.     // 判断类上是否有某个注解
  6.     boolean hasAnnotation = userClazz.isAnnotationPresent(Component.class);
  7.     if (hasAnnotation) {
  8.         // 获取类上的注解对象
  9.         Component component = userClazz.getAnnotation(Component.class);
  10.         // 访问注解的属性
  11.         System.out.println("component value: " + component.value());
  12.     }
  13. }
复制代码
组件扫描原理

告急是通过反射机制实例化注解标记的类的对象。
  1. public static void main(String[] args) {
  2.     // 根据一个包名,扫描这个包下面的所有类,当这个类有@Component注解时,实例化这个类,key是@Component注解的value,value是实例化的对象
  3.     String packageName = "com.ali.component";
  4.     // 将包名中的“.”替换成“/”
  5.     String path = packageName.replaceAll("\\.", "/");
  6.     // 包是在系统恨路径下的一个目录。获取它的绝对路径
  7.     String absolutePath = ClassLoader.getSystemClassLoader().getResource(path).getPath();
  8.     // 获取包下面的所有类文件
  9.     File dir = new File(absolutePath);
  10.     File[] files = dir.listFiles();
  11.     Arrays.stream(files).forEach(file -> {
  12.         // 获取类名
  13.         String classname = packageName + "." + file.getName().replace(".class", "");
  14.         // 通过反射机制解析注解
  15.         try {
  16.             Class<?> clazz = Class.forName(classname);
  17.             // 判断类上是否有某个注解
  18.             boolean hasAnnotation = clazz.isAnnotationPresent(Component.class);
  19.             if (hasAnnotation) {
  20.                 // 获取类上的注解对象
  21.                 Component component = clazz.getAnnotation(Component.class);
  22.                 // 访问注解的属性
  23.                 System.out.println("component value: " + component.value());
  24.                 // 实例化这个类
  25.                 Object obj = clazz.getDeclaredConstructor().newInstance();
  26.                 System.out.println("实例化对象: " + obj);
  27.             }
  28.         } catch (Exception e) {
  29.             e.printStackTrace();
  30.         }
  31.     });
  32. }
复制代码
声明bean的注解

声明bean的注解有:@Component 、@Controller、 @Service 、@Repository。
现实上 @Controller @Service @Repository 这3个都是@Component 的别名,本质上就是一个注解。告急是为了加强代码的可读性。
当这4个注解标注在类上是,如果没有指定value值(也就是没有指定bean名称),那么bean名称默认成类名的首字母小写。
选择性实例化bean

如果有一个需求:只必要@Controller到场bean的管理。其他三个注解都不到场实例化,这种环境要怎么处理处罚?
留意:别忘了添加设置文件的定名空间。
  1.    
  2.     <context:component-scan base-package="com.ali.bean2" use-default-filters="false">
  3.         
  4.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
  5.         <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
  6.     </context:component-scan>
  7.     <context:component-scan base-package="com.ali.bean2" >
  8.         
  9.         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  10.         
  11.         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
  12.     </context:component-scan>
复制代码
负责注入的注解

@value

@value:使用@value注入的话,属性可以不提供setter方法,负责注入简朴范例
  1. public class User {
  2.     @Value("Alice")
  3.     private String name;
  4.     @Value("22")
  5.     private int age;
  6. }
复制代码
@value注解也可以加在setter方法上
  1. public class User {
  2.     private String name;
  3.     private int age;
  4.     @Value("Alice")
  5.     public void setName(String name) {
  6.         this.name = name;
  7.     }
  8.     @Value("22")
  9.     public void setAge(int age) {
  10.         this.age = age;
  11.     }
  12. }
复制代码
@value注解也可以加在构造方法上
  1. public class User {
  2.     private String name;
  3.     private int age;
  4.     public User(@Value("Alice") String name,@Value("22") int age) {
  5.         this.name = name;
  6.         this.age = age;
  7.     }
  8. }
复制代码
@Autowired

@Autowired可以用来注入非简朴范例,翻译为:主动装配。
单独使用 @Autowired注解,默认根据范例装配【默认是byType】
留意:如果一个接口被2个或以上的类实现,那么这个接口对象能被 @Autowired注入吗?这固然不可,由于 @Autowired是根据范例举行装配的。
那怎么办理这个题目呢?
可以将@Autowired和@Qualifier团结使用
  1. @Autowired
  2. // 这里指定bean的名称,说明是根据名称进行自动装配的
  3. @Qualifier("someServiceBeanForMysql")
  4. private SomeService someService;
复制代码
@Autowired可以标注在属性上、setter方法上、构造方法的参数上。
当一个类中的构造方法只有一个,而且构造方法的参数和属性能对应上,@Autowired 可以省略 (不发起如许用)
@Resource

@Resource注解也能完成非简朴范例的注入,那么他和 @Autowired有什么区别呢?

  • @Resource是jdk扩展包中的,属于jdk的一部分,以是该注解是尺度注解,更加具有通用性。
  • @Autowired是spring框架本身的
  • @Resource默认根据名称主动装配,未指定name时,使用属性名作为name,如果通过name找不到的话。会启动通过范例主动装配。
  • @Autowired时根据范例主动装配。如果要根据名字装配,必要@Qualifier共同使用
  • @Resource用在属性上、setter方法上
  • @Autowired用在属性上、setter方法上、构造方法上、构造方法参数上。
使用@Resource时先参加干系依赖
  1.         <dependency>
  2.             <groupId>jakarta.annotation</groupId>
  3.             <artifactId>jakarta.annotation-api</artifactId>
  4.             <version>2.1.1</version>
  5.         </dependency>
复制代码
  1. // 进行属性注入
  2. @Resource(name = "someServiceBean")
  3. private SomeService someService;
复制代码
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表