Spring注解开发

Spring注解开发

常见注解

@ComponentScan

excludeFilters 排除过滤选择器
includeFilters 包含过滤选择器(使用该选择器需要设置useDefaultFilters = false)
FilterType.ANNOTATION 按照注解
FilterType.ASSIGNABLE_TYPE 按照给定的类型
FilterType.ASPECTJ 使用AspectJ表达式
FilterType.REGEX 使用正则表达式
FilterType.CUSTOM 使用自定义规则

示例:FilterType.CUSTOM

package org.example.filter;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

/**
 * 自定义组件扫描规则
 * @author admin
 */
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();
        //全类名中包含service的类注入ioc容器中
        if(className.contains("service")){
            //返回true注入ioc容器
            return true;
        }
        //返回false不注入ioc容器
        return false;
    }
}
@ComponentScan(value = "org.example", useDefaultFilters = false, includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
})

@Configuration

作用:告诉spring这是一个配置类,并将该类注入ioc容器

/**
 * @Configuration 表示该类是一个配置类
 */
@Configuration
public class SpringConfig {
    
}

@Scope

作用:设置Bean的作用域

@Scope 设置Bean的作用域
     prototype 多例(获取对象时创建对象)
     singleton 单例(默认,ioc容器初始化时创建对象)
     request 同一次请求创建一个实例
     session 同一次会话创建一个实例
@Scope("prototype")
public Person person(){
    return new Person("李四",22);
}

@Lazy

作用:懒加载

​ 单例bean默认在容器初始化时创建对象;

​ 懒加载后,容器初始化时不创建对象,第一次获取bean对象时创建对象并初始化。

@Conditional

作用:按照条件将bean注入到ioc容器中

package org.example.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * 系统环境为Linux时将bean注入到ioc容器中
 * @author admin
 */
public class LinuxCondition implements Condition {

    /**
     *
     * @param conditionContext 判断条件能使用的上下文
     * @param annotatedTypeMetadata 注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取ioc容器使用beanFactory(bean工厂)
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        System.out.println(beanFactory);
        System.out.println(classLoader);
        System.out.println(environment);
        System.out.println(registry);
        String osName = environment.getProperty("os.name");
        if(osName.contains("Linux")){
            return true;
        }
        return false;
    }
}
package org.example.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * 系统环境为Window时将bean注入到ioc容器中
 * @author admin
 */
public class WindowCondition implements Condition {

    /**
     *
     * @param conditionContext 判断条件能使用的上下文
     * @param annotatedTypeMetadata 注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取ioc容器使用beanFactory(bean工厂)
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        System.out.println(beanFactory);
        System.out.println(classLoader);
        System.out.println(environment);
        System.out.println(registry);
        String osName = environment.getProperty("os.name");
        if(osName.contains("Window")){
            return true;
        }
        return false;
    }
}
@Bean
@Conditional({WindowCondition.class})
public Person person(){
    return new Person("李四",22);
}

@Bean
@Conditional({LinuxCondition.class})
public Student student(){
    return new Student("1001","张三");
}

@Import

作用:将组件注入到ioc容器中,id默认为全类名

ImportSelector

package org.example.filter;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Set;

/**
 * 自定义需要注入ioc容器的组件
 * @author admin
 */
public class MyImportSelector implements ImportSelector {
    /**
     * 返回值就是导入ioc容器中组件的全类名
     * @param annotationMetadata
     * @return
     */
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"org.example.pojo.Color"};
    }
}

ImportBeanDefinitionRegistrar

package org.example.filter;

import org.example.pojo.Color;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author admin
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param importingClassMetadata 当前类的注解信息
     * @param registry beanDefinition注册类
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        registry.registerBeanDefinition("color", new RootBeanDefinition(Color.class));
        String[] beanDefinitionNames = registry.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }
}

示例:

@Configuration
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.})
public class SpringConfig {
    
}

@PropertySource

作用:加载配置文件

package org.example;

import org.example.pojo.Person;
import org.springframework.context.annotation.*;

/**
 * @PropertySource 将person.properties配置文件加载到运行环境中
 */
@Configuration
@PropertySource({"classpath:person.properties"})
public class SpringConfig {
    @Bean
    public Person person(){
        return new Person();
    }
}

@Value

作用:给对象中的属性赋值

package org.example.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    /**
     * 使用@Value赋值
     *  1、基本类型的值
     *  2、可以写SpEL;#{}
     *  3、可以写${};取出配置文件中的值(在运行环境)
     */
    @Value("未知")
    private String name;
    @Value("#{5-5}")
    private int age;
    @Value("${nickname}")
    private String nickname;
}

@Autowired

作用:默认按照类型自动注入

package org.example.controller;

import lombok.Data;
import org.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author admin
 */
@Controller
@Data
public class UserController {

    /**
     * @Autowired 默认按照类型去容器中找对应的组件,如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
     */
    @Autowired
    private UserService userService;

    public void show(){
        System.out.println("userController-show");
    }
}

@Qualifier

作用:配合@Autowired使用,按照组件id装配

package org.example.controller;

import lombok.Data;
import org.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

/**
 * @author admin
 */
@Controller
@Data
public class UserController {

    /**
     * @Qualifier 如果找到多个相同类型的组件,根据组件id自动装配
     */
    @Autowired
    @Qualifier("userService")
    private UserService userService;

    public void show(){
        System.out.println("userController-show");
    }
}

@Primary

作用:spring自动装配的时候,默认使用首选的bean,也可以继续使用@Qualifier指定需要装配的bean的名字

@Resource(JSR50)

作用:和@Autowired一样实现自动装配功能;默认按照组件名称进行装配

注意:不支持@Primary注解

@Inject(JSR330)

作用:和@Autowired功能一样

注意:需要导入javax.inject包

@Profile

作用:指定组件在哪个环境的情况下才能被注册到容器中,如果不指定则任何环境下都能注册这个组件

@Configuration
@ComponentScan("org.example")
public class SpringConfig {

    @Bean
    @Profile("pro")
    public DataSource dataSourcePro(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setMaxPoolSize(100);
        return dataSource;
    }

    @Bean
    @Profile("dev")
    public DataSource dataSourceDev(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setMaxPoolSize(10);
        return dataSource;
    }
}
@Test
public void testProfile(){
    //用代码的方式激活环境
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.getEnvironment().setActiveProfiles("pro");
    context.register(SpringConfig.class);
    context.refresh();
    ComboPooledDataSource dataSource = (ComboPooledDataSource) context.getBean(DataSource.class);
    System.out.println(dataSource.getMaxPoolSize());
}

Aop

package org.example.aop;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
public class MathUtil {
    public int div(int i, int j){
        return i/j;
    }
}
package org.example.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* org.example.aop.MathUtil.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(joinPoint.getSignature().getName()+"开始执行。。。参数列表是:"+ Arrays.asList(args));
    }

    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName()+"执行结束。。。");
    }

    @AfterReturning(value = "pointCut()", returning = "result")
    public void logReturn(Object result){
        System.out.println("除法返回结果。。。结果为:{"+ result +"}");
    }

    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception){
        System.out.println(joinPoint.getSignature().getName() + "执行异常。。。异常信息:{"+ exception +"}");
    }
}
package org.example;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.example.condition.LinuxCondition;
import org.example.condition.WindowCondition;
import org.example.factory.ColorFactoryBean;
import org.example.filter.MyImportBeanDefinitionRegistrar;
import org.example.filter.MyImportSelector;
import org.example.filter.MyTypeFilter;
import org.example.pojo.Color;
import org.example.pojo.Person;
import org.example.pojo.Student;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;

/**
 * @EnableAspectJAutoProxy 开启spring aop自动代理
 */
@Configuration
@ComponentScan("org.example")
@EnableAspectJAutoProxy
public class SpringConfig {

}
@Test
public void testAop(){
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    MathUtil math = context.getBean(MathUtil.class);
    int result = math.div(2, 0);
    System.out.println("结果为:"+result);
}

声明式事务

package org.example.dao;

import org.example.pojo.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author admin
 */
@Repository
public class AccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Account queryAccountById(int id){
        Account account = jdbcTemplate.queryForObject("select * from account where id=?", new BeanPropertyRowMapper<>(Account.class), id);
        return account;
    }

    public List<Account> queryAllAccount(){
        List<Account> accounts = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
        return accounts;
    }

    public int updateAccount(Account account){
        int row = jdbcTemplate.update("update account set name=?,money=? where id=?", account.getName(), account.getMoney(), account.getId());
        return row;
    }
}
package org.example.service;

import org.example.dao.AccountDao;
import org.example.pojo.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author admin
 */
@Service
public class AccountService {
    @Autowired
    private AccountDao accountDao;

    public List<Account> queryAllAccount(){
        List<Account> accounts = accountDao.queryAllAccount();
        return accounts;
    }

    public Account queryAccountById(int id){
        Account account = accountDao.queryAccountById(id);
        return account;
    }

    @Transactional
    public boolean updateAccount(Account account){
        int row = accountDao.updateAccount(account);
        if(row>0){
            return true;
        }
        return false;
    }
}
package org.example;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.example.condition.LinuxCondition;
import org.example.condition.WindowCondition;
import org.example.factory.ColorFactoryBean;
import org.example.filter.MyImportBeanDefinitionRegistrar;
import org.example.filter.MyImportSelector;
import org.example.filter.MyTypeFilter;
import org.example.pojo.Color;
import org.example.pojo.Person;
import org.example.pojo.Student;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@Configuration
@ComponentScan("org.example")
@EnableTransactionManagement
public class SpringConfig {

    @Bean
    public TransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql:///test?characterEncoding=utf-8&useSSL=true&serverTimezone=UTC");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
}
@Test
public void testAccountService(){
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    AccountService accountService = context.getBean(AccountService.class);
    Account account = accountService.queryAccountById(1);
    account.setMoney(5000d);
    boolean flag = accountService.updateAccount(account);
    System.out.println("转账是否成功:" + flag);
    Account accountForAfter = accountService.queryAccountById(account.getId());
    System.out.println(accountForAfter);
}
posted @ 2022-01-23 14:00  (x²+y²-1)³=x²y³  阅读(38)  评论(0编辑  收藏  举报