Spring基础知识点 - 注解详解

XML文件配置

// 使用xml配置文件完成Spring容器的创建
public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) context.getBean("person");
    }
}
<!-- applicationContext.xml配置文件 -->
<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="person" class="top.kiqi.spring.demo.xml.project.Person">
        <property name="name" value="kiqi"></property>
        <property name="age" value="26"></property>
    </bean>
</beans>

Annotation注解

beanDefinition

@Configuration

@Configuration: 用于定义配置类,替代application.xml配置文件(等价于<Beans></Beans>)

// spring configuration类作为配置类(@Configuration) --- AnnotationConfigApplicationContext
// @Bean注解,默认以方法名作为bean name.
public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        Person person = (Person) context.getBean("person");
        System.out.println(person);
    }
}

@Configuration
public class MyConfiguration {
    @Bean
    public Person person(){
        return new Person("kiqi",17);
    }
}

@ComponentScan

@ComponentScan:配置扫描路径(等价于<context:component-scan base-package="*"/>)

@Configuration
@ComponentScan(value = "top.kiqi.spring.demo.annotation.project", useDefaultFilters = true)
//        includeFilters = {@Filter(type = FilterType.ANNOTATION,value = {Controller.class})},useDefaultFilters = false)
//        includeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE,value = {UserBO.class})},useDefaultFilters = false)
//        includeFilters = {@Filter(type = FilterType.CUSTOM,value = {MyTypeFilter.class})},useDefaultFilters = false))
public class MyConfiguration {}

// @ComponentScan注解,配置扫描路径以及过滤方式(Filter:默认扫描含有@Component,@Service,@Controller和@Repository注解的类)
// @Filter(type = FilterType.ANNOTATION,value = {Controller.class}  --- 注解式过滤器,注册所有带@Controller注解的类
// @Filter(type = FilterType.ASSIGNABLE_TYPE,value = {UserBO.class} --- 类型式过滤器,注册类型为UserBO.class的类
// @Filter(type = FilterType.CUSTOM,value = {MyTypeFilter.class} --- 采用用户创建的过滤器进行过滤
// 类型拦截器,用于@ComponentScan注解中设置类的过滤方式
public class MyTypeFilter implements TypeFilter{
    /**
     * @param metadataReader 获取当前正在操作的信息
     * @param metadataReaderFactory 获取上下文中所有的信息
     * @return
     * @throws IOException
     */
    @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("BO")){
            System.out.println("register bean : " + className);
            return true;
        }
        return false;
    }
}

@Scope

@Scope:设置Bean对象的作用域

// @scope注解,默认 单例
//  prototype 多例
//  singleton 单例
//  request 主要应用于web模块,同一次请求只创建一个实例
//  session 主要应用于web模块,同一个session只创建一个实例

@Configuration
public class MyConfiguration {
    @Bean
    @Scope("prototype")
    public Person person(){
        return new Person("kiqi",17);
    }
}

@Lazy

@Lazy:设置Bean对象是否懒加载

// @Lazy注解 - 默认值为true
// 若未设置Lazy注解,对于单例对象,默认提前加载
// 若未设置Lazy注解,对于原型对象,默认懒加载
@Configuration
public class MyConfiguration {
    @Bean
    @Lazy()
    public Person person(){
        return new Person("kiqi",17);
    }
}

@Conditional

@Conditional:条件加载,只有符合条件时,才会加载Bean到容器中

// @Condition注解,条件加载,只有符合条件时,才会加载Bean到容器中
// @PropertySource("application.properties")  读取解析配置文件并加入到容器的Environment中
public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        UserBO userBO = context.getBean("userBO", UserBO.class);
        System.out.println(userBO);
    }
}

// 条件对象,实现Condition
public class ConditionLinux implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String name = environment.getProperty("io.name", "Linux");
        return name.contains("inux");
    }
}

@Configuration
@PropertySource("application.properties")
public class MyConfiguration {
    @Conditional(ConditionWindows.class)
    @Bean("userBO")
    public UserBO windows(){
        System.out.println("条件注入 - windows");
        return new UserBO("windows",17);
    }

    @Conditional(ConditionLinux.class)
    @Bean("userBO")
    public UserBO linux(){
        System.out.println("条件注入 - linux");
        return new UserBO("linux",16);
    }
}

@Import

@Import:向IOC容器中导入Bean

// Configuration类
// Import导入 ①普通Bean,②ImportSelector实现类,③ImportBeanDefinitionRegistrar实现类。
@Configuration
@Import(value = {ImportClass.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfiguration {
    @Bean
    // FactoryBean,实际会将:importFactoryBeanBean实例注册到IOC容器中
    public MyFactoryBean importFactoryBeanBean(){
        return new MyFactoryBean();
    }
}
// FactoryBean类
// 获取Bean对象时,会调用getObject()方法将真实对象注册到IOC容器(如果是解引用&获取,则返回FactoryBean对象)
public class MyFactoryBean implements FactoryBean<ImportFactoryBeanBean> {
    @Override
    public ImportFactoryBeanBean getObject() throws Exception {
        return new ImportFactoryBeanBean();
    }

    @Override
    public Class<?> getObjectType() {
        return ImportFactoryBeanBean.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
// ImportSelector类
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{
                "top.kiqi.spring.demo.annotation.core.configure.a4_import.entity.ImportSelectorBean"
        };
    }
}
// ImportBeanDefinitionRegistrar类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * @param annotationMetadata  当前类的注解信息
     * @param registry 完成BeanDefinition的注册
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
        boolean person = registry.containsBeanDefinition("top.kiqi.spring.demo.annotation.core.configure.a4_import.entity.ImportClass");

        if(person){
            BeanDefinition beanDefinition = new RootBeanDefinition(ImportRegistrarBean.class);
            registry.registerBeanDefinition("importRegistrarBean",beanDefinition);
        }
    }
}

向IOC容器中注册Bean的方式:

  1. @Bean:Configuration类中,直接导入单个类
  2. @ComponentScan:包扫描,默认扫描@Controller、@Service、@Repository、@Component注解类
  3. @Import:快速给容器导入组件Bean
    • BeanName 直接导入单个Bean(beanName为全类名)
    • ImportSelector 自定义导入规则
    • ImportBeanDefinitionRegistrar 使用BeanDefinitionRegistry手动导入Bean到IoC容器中

FactoryBean接口:为需要注入的对象创建FactoryBean,由FactoryBean.getObject()将Bean注入到容器的Bean

population

  • Component
    • @Component:泛指组件
    • @Controller:控制层组件
    • @Service:业务层组件
    • @Repository(DAO):数据访问层组件
  • DI
    • @Value:普通数据类型赋值 ①直接赋值 ②\({},El表达式赋值 ③\){},从配置文件中获取
    • @Autowired默认按类型(byType)装配,当和Qualifier("name")一同使用时,为按名称(byName)装配
    • @Qualifier 如上
    • @Resource默认按名称(byName)装配,如果找不到与名称匹配的bean时,会按类型(byType)装配
  • @PropertySource:加载配置文件,并将属性保存到ApplicationContext的Environment中
  • @Primary:自动装配时,当出现多个Bean候选时,将选用带有Primary标签的bean

aspects

  • @EnableAspectJAutoProxy:开启AOP切面代理
  • @Aspect:声明类为切面类
  • @Pointcut(EL表达式):声明切面(通过EL表达式筛选出所有需要切入的方法 - 即:切点)
  • Advice
    • @Before: 前置通知
    • @Around:环绕通知(前置先于普通前置通知执行,后置先于普通后置通知执行)
    • @After: 后置通知(普通后置通知先于条件后置通知执行)
    • @AfterReturning:正常返回情况下后置通知
    • @AfterThrowing:抛出异常情况下后置通知
@Aspect
@Component
public class LogAspect {
    // EL表达式,代理所有带有LogAnnotation注解的类和方法。
    @Pointcut("@annotation(top.kiqi.spring.demo.annotation.core.aspects.annotation.LogAnnotation)")
    public void pointCut(){}

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint){
        System.out.println("Before Advice...");
        System.out.println("-- 目标方法名为:" + joinPoint.getSignature().getName());
        System.out.println("-- 目标方法所属类的简单类名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("-- 目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("-- 目标方法声明类型:" + joinPoint.getSignature().getModifiers());
        //获取传入目标方法的参数
        Object[] args = joinPoint.getArgs();

        System.out.println("-- 被代理的对象:" + joinPoint.getTarget());
        System.out.println("-- 代理对象自己:" + joinPoint.getThis());
    }

    @Around("pointCut()")
    public void around(ProceedingJoinPoint pjp){
        System.out.println("Aronud before...");
        try {
            pjp.proceed();
        } catch (Throwable e) {
            System.out.println("Aronud throw...");
            e.printStackTrace();
        }
        System.out.println("Aronud after...");
    }

    @After("pointCut()")
    public void doAfter(JoinPoint joinPoint){
        System.out.println("After Advice...");
    }

    @AfterReturning(pointcut="pointCut()",returning="returnVal")
    public void afterReturn(JoinPoint joinPoint,Object returnVal){
        System.out.println("After Returning Advice:" + returnVal);
    }

    @AfterThrowing(pointcut="pointCut()",throwing="error")
    public void afterThrowing(JoinPoint joinPoint,Throwable error){
        System.out.println("After Throwing Advice..." + error);
    }
}

// 自定义注解类
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {
    String value() default "default";
}

事务注解

  • @EnableTransactionManagement:开启Spring事务代理
  • @Transactional:声明事务
    • propagation:事务传播特性(REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED)
    • isolation:事务隔离级别(DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE)
    • readOnly:方法中没有需要处理的事务,比如读取数据,可以设置 read-only 为 true
    • timeout:事务超时时间
    • rollbackFor:设置当抛出何种异常时执行回滚操作(默认在遇到RuntimeException的时候会回滚)

Aware类接口

如果一个Bean想要依赖注入一些特殊的与Spring容器有关的属性,需要Bean类实现Aware接口。
- BeanNameAware:beanName
- BeanClassLoaderAware:beanClassLoader
- BeanFactoryAware:beanFactory
- EnvironmentAware:environment
- ApplicationContextAware:applicationContext

posted @ 2021-01-29 22:42  祁奇  阅读(63)  评论(0编辑  收藏  举报