Spring 从 2.5 版本开始提供了对注解技术的全面支持,我们可以使用注解来实现自动装配,简化 Spring 的 XML 配置。
Spring 通过注解实现自动装配的步骤如下:
①添加依赖
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>6.0.13version>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiter-apiartifactId>
<version>5.9.3version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.20.0version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-slf4j2-implartifactId>
<version>2.20.0version>
dependency>
dependencies>
AppConfig.java
package com.mcode.config;
import com.mcode.controller.UserController;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
/**
* ClassName: AppConfig
* Package: config
* Description:
*
* @Author: robin
* @Create: 2023/11/8 - 9:46 PM
* @Version: v1.0
*/
@ComponentScan("com.mcode")
public class AppConfig {
}
ComponentScan
顾名思义包扫描,底层其实就可以通过递归算法+反射将其装载成bean来实现的,实在开发过程中,Spring已经帮我们实现好了,我们其实就可以直接使用XML或者注解的形式来进行业务处理。
@ComponentScan注解有两个作用
作用一:扫描含有@Component,@Controller,@Service和@Repository的类,并将其注入到spring容器中。
作用二:扫描含有@Configuration的类,并使其生效。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)//可重复注解
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};//基础包名,等同于basePackages
@AliasFor("value")
String[] basePackages() default {};//基础包名,value
Class<?>[] basePackageClasses() default {};//扫描的类,会扫描该类所在包及其子包的组件。
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;//注册为BeanName生成策略 默认BeanNameGenerator,用于给扫描到的Bean生成BeanName
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;//用于解析bean的scope的属性的解析器,默认是AnnotationScopeMetadataResolver
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;//scoped-proxy 用来配置代理方式 // no(默认值):如果有接口就使用JDK代理,如果没有接口就使用CGLib代理 interfaces: 接口代理(JDK代理) targetClass:类代理(CGLib代理)
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;//配置要扫描的资源的正则表达式的,默认是"**/*.class",即配置类包下的所有class文件。
boolean useDefaultFilters() default true;//useDefaultFilters默认是true,扫描带有@Component ro @Repository ro @Service ro @Controller 的组件
Filter[] includeFilters() default {};//包含过滤器
Filter[] excludeFilters() default {};//排除过滤器
boolean lazyInit() default false;//是否是懒加载
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {//过滤器注解
FilterType type() default FilterType.ANNOTATION;//过滤判断类型
@AliasFor("classes")
Class<?>[] value() default {};//要过滤的类,等同于classes
@AliasFor("value")
Class<?>[] classes() default {};//要过滤的类,等同于value
String[] pattern() default {};// 正则化匹配过滤
}
}
演示
@ComponentScan(value = "com.mcode", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = {UserController.class})},
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Component.class})}
)
Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。
注解 | 说明 |
---|---|
@Component | 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。 |
@Repository | 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Service | 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Controller | 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
单独写一个配置类来配置Bean
单独使用@Autowired注解,默认根据类型装配。【默认是byType】
查看源码:
源码中有两处需要注意:
第一处:该注解可以标注在哪里?
第二处:该注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须是存在的,如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系,存在的话就注入,不存在的话,也不报错。
@Autowired注解可以出现在:属性上、构造方法上、构造方法的参数上、setter方法上。
当带参数的构造方法只有一个,@Autowired注解可以省略。()
@Autowired注解默认根据类型注入。如果要根据名称注入的话,需要配合@Qualifier注解一起使用。
@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?
@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。】
<dependency>
<groupId>jakarta.annotationgroupId>
<artifactId>jakarta.annotation-apiartifactId>
<version>2.1.1version>
dependency>
UserDaoImpl
package com.mcode.dao.impl;
import com.mcode.dao.UserDao;
import org.springframework.stereotype.Repository;
/**
* ClassName: UserDaoImpl
* Package: com.mcode.dao.impl
* Description:
*
* @Author: robin
* @Create: 2023/11/8 - 9:54 PM
* @Version: v1.0
*/
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("user dao...");
}
}
UserDao
package com.mcode.dao;
/**
* ClassName: UserDao
* Package: com.mcode.dao
* Description:
*
* @Author: robin
* @Create: 2023/11/8 - 9:54 PM
* @Version: v1.0
*/
public interface UserDao {
void getUser();
}
UserServiceImpl
package com.mcode.service.impl;
import com.mcode.dao.UserDao;
import com.mcode.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* ClassName: UserServiceImpl
* Package: com.mcode.service.impl
* Description:
*
* @Author: robin
* @Create: 2023/11/8 - 9:48 PM
* @Version: v1.0
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void getUser() {
userDao.getUser();
}
}
UserService
package com.mcode.service;
/**
* ClassName: UserService
* Package: com.mcode.service
* Description:
*
* @Author: robin
* @Create: 2023/11/8 - 9:47 PM
* @Version: v1.0
*/
public interface UserService {
void getUser();
}
UserController
package com.mcode.controller;
import com.mcode.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
/**
* ClassName: UserController
* Package: com.mcode.controller
* Description:
*
* @Author: robin
* @Create: 2023/11/8 - 9:49 PM
* @Version: v1.0
*/
@Controller
public class UserController {
@Autowired
private UserService userService;
public void getUser(){
userService.getUser();
}
}
AppTest
package com.mcode;
import com.mcode.config.AppConfig;
import com.mcode.controller.UserController;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Hello world!
*
*/
public class AppTest
{
@Test
public void testAnnotation(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserController userController = (UserController) context.getBean(UserController.class);
userController.getUser();
}
}