Spring5注解编程基础组件

配置类组件

注解说明
@Configuratioin把一个类作为IoC容器,它的某个方法上如果添加了@Bean,那么就会作为这个Spring容器中的Bean。
@ComponentScan在配置类上添加此注解,该注解默认扫描该类所在包下的所有配置类,相当于之前的<context:component-scan>
@Scope用于指定scope作用域(用在类上)
@Lazy表示延迟初始化
@ConditionalSpring4开始提供,作用是按照一定的条件进行判断,如果满足条件则给容器注册Bean
@Import导入外部资源
生命周期控制

@PostConstruct用于指定初始化方法(用在方法上)

@PreDestroy用于指定销毁方法(用在方法上)

@DependsOn定义Bean初始化和销毁的顺序

@Configuratioin

原始xml方式写法

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="com.lucifer.project.entity.User">
        <property name="username" value="Lucifer"/>
        <property name="address" value="xian"/>
        <property name="age" value="18"/>
    </bean>
</beans>

调用方式

public class MyTest {
    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        // 如果定义了bean的id,优先以自定义value为准
        // 如果没定义,默认获取类名首字母小写
        Object user = ac.getBean("user");
        System.out.println(user); // User{username='Lucifer', address='xian', age=18}
    }
}

使用@Configuration注解

@Configuration
public class MyConfig {
    // 默认获取类名首字母小写,其次是方法名
    // 如果定义了@Bean的value,优先以自定义value为准
    @Bean("user")
    public User user() {
        return new User("Lucifer", "xian", 18);
    }
}
public class MyTest {
    @Test
    public void test2() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
        // Bean name默认是是方法名
        // 如果定义了@Bean的value,优先以自定义value为准
        Object user = ac.getBean("user");
        System.out.println(user); // User{username='Lucifer', address='xian', age=18}
    }
}

@ComponentScan

原始xml方式写法

<context:component-scan base-package="com.lucifer.project.entity"/>

通过注解写法

@Configuration
@ComponentScan(value = "com.lucifer.project",
        //includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)},
        includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyController.class)},
        includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, value = MyTypeFilter.class)},
        useDefaultFilters = false)
public class ComponentScanConfig {
}
public class MyTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类所有的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前扫描到的类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取到当前类的所有资源
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        if (className.contains("Controller")) {
            return true;
        }
        return false;
    }
}
public class MyTest {
    @Test
    public void test3() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentScanConfig.class);
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        System.out.println(Arrays.toString(beanDefinitionNames).replaceAll(",", "\n"));
    }
}

@Scope

Scope有四种范围:

singleton:单例,默认scope
prototype:原型,多例,每次都会是新的一个对象
request:主要用于web模块,同一次请求值创建一个实例
session:主要用于web模块, 同一个session只创建一个实例
@Configuration
public class MyConfig {
    @Scope("singleton")
    public User user() {
        return new User("Lucifer", "xian", 18);
    }
}

@Lazy:使当前类延时加载

默认不延时加载,如果加上此注解则使当前类延时加载
延时加载只针对单例Bean(即@Scope为singleton的Bean)起作用
加上此注解后容器启动时不创建对象,调用对象的功能时才创建对象

@Configuration
public class MyConfig {
    @Lazy //延迟加载,调用此对象时才会去创建,默认不延迟加载
    public User user() {
        return new User("Lucifer", "xian", 18);
    }
}

@Conditional

@Configuration
public class MyConfig {
    @Scope("singleton")
    @Lazy
    @Bean
    public User user() {
        System.out.println("将对象user添加到容器中");
        return new User("Lucifer", "xian", 18);
    }

    @Conditional(WindowsCondition.class)
    @Bean
    public User john() {
        System.out.println("将John添加到容器中");
        return new User("John", "xian", 17);
    }
    @Conditional(LinuxCondition.class)
    @Bean
    public User mandy() {
        System.out.println("将mandy添加到容器中");
        return new User("Mandy", "xian", 16);
    }
}
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String osName = environment.getProperty("os.name");
        System.out.println(osName);
        if (osName.contains("Windows")) {
            return true;
        }
        return false;
    }
}

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String osName = environment.getProperty("os.name");
        System.out.println(osName);
        if (osName.contains("Linux")) {
            return true;
        }
        return false;
    }
}
    @Test
    public void test2() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println("IoC容器创建完成");
    }

@Import

在一个Spring bean类上加@Import(value = User.class)去注入User对象
@Configuration
@Import(value = {User.class})
public class MyConfig {
    public User user() {
        return new User("Lucifer", "xian", 18);
    }
}

给IoC容器注册Bean的方式:

1. 通过@Bean直接导入单个类

2. 通过@ComponentScan扫描包,默认扫描(@Controller, @Service, @Repository, @Component)

3. 通过@Import快速给容易导入Bean

3.1 通过@Import(User.class) 直接参数导入单个类

3.2 实现ImportSelector 自定义导入规则实现

3.3 实现ImportBeanDefinitionRegistrar,获得BeanDefinitionRegistry可以手动直接往IoC容器中注册Bean

4. 通过FactoryBean将bean注册到容器

通过ImportSelector自定义导入规则

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[] {"com.lucifer.project.model.Person"};
    }
}
@Configuration
@Import(value = {User.class, MyImportSelector.class})
public class MyConfig {
    public User user() {
        return new User("Lucifer", "xian", 18);
    }
}

通过ImportBeanDefinitionRegistrar往容器导入bean

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean person = registry.containsBeanDefinition("com.lucifer.project.model.Person");
        if (person) {
            BeanDefinition beanDefinition  = new RootBeanDefinition(Person.class);
            registry.registerBeanDefinition("person", beanDefinition);
        }
    }
}

通过FactoryBean将bean注册到容器

public class MyFactoryBean implements FactoryBean<Animal> {
    @Nullable
    @Override
    public Animal getObject() throws Exception {
        return new Animal();
    }

    @Nullable
    @Override
    public Animal getObjectType() {
        return Animal.class;
    }
    
    @Override
    public boolean isSingleton() {
        return true;
    }
}
@Configuration
@Import(value = {User.class, MyImportSelector.class})
public class MyConfig {
    @Bean
    public MyFactoryBean animal() {
        return new MyFactoryBean(); 
    }   
}
public class MyTest {
    @Test
    public void test() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
        Object obj= ac.getBean("animal");
        System.out.println(obj.getClass()); // 打印的结果是com.lucifer.project.model.Animal
    }
}

赋值(自动装配)组件

注解说明
@Component泛指组件,当组件不好归类的时候,使用这个注解进行标注
@Service用于标注业务层组件
@Controller用于标注控制层组件
@Repository用于标注数据访问层组件,即DAO组件
@Value普通数据类型赋值
@Autowired默认按类型装配,如果想按名称装配,可以结合@Qualifier注解一起使用

@PropertySource

读取配置文件赋值  

@Qualifier如存在多个实例,配合使用,优先级高于@Autowired
@Primary自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Resource默认按名称装配,当找不到与名称匹配的Bean时才会按类型匹配

@Component

声明这个类需要被注册到IoC容器中

@Component
public class MyTypeFilter implements TypeFilter {}

@Service

如果是业务层组件,则用此注解,同样会被注册到IoC容器中

@Service
public class UserService {
    @Autowired
    UserDao userDao;

    public User findById(String id) {
        return userDao.findById(id);
    }
    public User update(User user) {
        return userDao.update(user);
    }
    public void delete(String id) {
        userDao.delete(id);
    }
}

@Controller

如果是控制层组件,则用此注解,同样会被注册到IoC容器中

@Controller
public class UserController {}

@Repository

如果是数据访问层组件,则用此注解,同样会被注册到IoC容器中

@Repository
public class UserDao {
    public User findById(String id) {
       return null;
    }
    public User update(User user) {
        return null;
    }
    public void delete(String id) {

    }
}

@Value

public class User {
    @Value("Lucifer") //支持基本数据类型
    private String username;
    @Value("${user.address}") //通过@PropertySource("classpath:values.properties")读取配置文件取值
    private String address;
    @Value("#{2021-1991}") //支持Spring EL表达式
    private int age;
}

values.properties配置文件

user.address=SHAN'XI

@PropertySource

@Configuration
@PropertySource("classpath:values.properties")
public class MyConfig {
    @Bean
    public User user() {
        System.out.println("将对象user添加到容器中");
        return new User();
    }
}

从环境变量Environment中取值

public class MyTest {
    @Test
    public void test() {
        ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println("IoC容器创建完成");
        String address = app.getBean("user.address");
        // 从环境变量中取值
        Environment env = app.getEnvironment();
        env.getProperty("user.address");
    }
}

@Autowired

默认按类型装配,如果想按名称装配,可以结合@Qualifier注解一起使用

@Controller
public class UserController {
    @Autowired
    UserService userService;
}

@Service
public class UserService {
    @Autowired
    UserDao userDao;
    public User findById(String id) {
        return userDao.findById(id);
    }
    public User update(User user) {
        return userDao.update(user);
    }
    public void delete(String id) {
        userDao.delete(id);
    }
}

@Repository
public class UserDao {
    public User findById(String id) {
       return null;
    }
    public User update(User user) {
        return null;
    }
    public void delete(String id) {
    }
}

@Qualifier

如存在多个实例,配合@Autowired使用,优先级高于@Autowired,但是无法单独使用

@Configuration
public class MyConfig {
    @Bean("userDao")
    public UserDao userDao() {
        return new UserDao();
    }
}
@Service
public class UserService {
    @Autowired
    @Qualifier("userDao")
    UserDao userDao;
}

@Resource

可以单独使用,优先级更高

@Service
public class UserService {
    @Resource(name = "userDao")
    UserDao userDao;
}

@Primary

如果Spring容器中存在多个相同名字的Bean,使用@Primary注解可以提高优先级,成为首选者,否则报错

@Configuration
public class MyConfig {
    // 使用当前实例
    @Primary
    @Bean("userDao")
    public UserDao userDao() {
        return new UserDao();
    }

    @Bean("userDao")
    public UserDao userDao2() {
        return new UserDao();
    }
}

织入组件

注解说明
ApplicationContextAware可以通过这个上下文环境对象得到Spring容器中的Bean
BeanDefinitionRegistryPostProcessorBeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是Spring框架的BeanFactoryRegistry的后处理器,用来注册额外的BeanDefinition


切面组件

注解说明
@EnableTransactionManagement添加对事务管理的支持
@Transactional配置声明式事务信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值