Spring基于纯注解方式的使用

经过上篇xml与注解混合方式,对注解有了简单额了解,上篇的配置方式极大地简化了xml中配置,但仍有部分配置在xml中进行,接下来我们就通过注解的方式将xml中的配置用注解的方式实现,并最终去掉xml配置。

一、xml中遗留配置

注解扫描

<!-- 开启注解并扫描指定包中带有注解的类 -->
<context:component-scan base-package="com.kkb.spring.service"/>

非自定义bean,如sqlsessionFactory

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" value="dataSource"></property>
</bean>

下面将用注解的方式进行替代。

二、组件注册

首先是@Configuration注解,被其修饰的类可看做xml配置文件,通过此类进行组件注册。而上下文容器可通过下面方式进行创建:

ApplicationContext context = new    AnnotationConfigApplicationContext(SpringConfiguration.class);

其中,SpringConfiguration是被@Configuration修饰的配置类。

1、@Bean注解

@Bean是Spring提供的注解,它在配置类中使用,可以将Java类交给Spring进行管理,@Bean有如下特征:

  • 默认时,以@Bean修饰的bean对象对应的关键字是【方法名】
  • 如果在@Bean指定bean对象对应关键@Bean(value={"stu1","stu2"}),此时bean对象在Spring容器对应关键字就不是【方法名】,是stu1或则stu2
  • 所有通过@Bean修饰生成的bean对象默认的情况下都是单例。
  • 对于单例的bean对象,可以通过@Lazy延缓变对象被创建时机。
@Configuration//相当于配置文件
public class ApplicationConfig {

    @Bean(value={"stu1"})
    public Student student2(){
        return new Student();
    }

    //这个注解专用于单例模式bean对象,此时bean对象不会在,spring容器启动时被创建的,只有在一个用户来访时才会被创建
    @Lazy
    @Bean
    public Teacher teacher(){
        return new Teacher();
    }
}

2、@ComponentScan注解

@ComponentScan是Spring中的注解,在配置类中使用,用于配置扫描的类,它可以将某些类排除在Spring容器之外,也可以将某些类添加到Spring容器之内 。相当于context:component-scan标签

@ComponentScan(value="com.kkb.beans")
@Configuration//相当于配置文件
public class ApplicationConfig {}

可以在@ComponentScan中配置FilterType进行扫描文件的过滤,FilterType提供五种扫描策略:

  • ANNOTATION 根据注解进行过滤(@Controller,@Service,@Resposity,@Compoent)
  • ASSIGNABLE_TYPE 根据指定类型
  • ASPECTJ表达式过滤
  • REGEX根据正则表达式过滤
  • CUSTOM,根据开发人员自行定义过滤规则

2.1、将指定类添加到Spring容器中

将指定的类添加Spring容器使用includeFilters

@ComponentScan(value="com.luis.beans",useDefaultFilters=false,
             includeFilters={
                      @Filter(type=FilterType.ANNOTATION,
                               value={Controller.class,Service.class}),

                      @Filter(type=FilterType.ASSIGNABLE_TYPE,
                              value={DeptDao.class})
               })
@Configuration//相当于配置文件
public class ApplicationConfig {

}

上面的代码采用了1,2两个策略将指定类添加到Spring容器中。

自定义扫描规则的配置如下:

在@ComponentScan(value="包路径",
              excludeFilters={
                        @Filter(type=FilterType.CUSTOM,value=自定义过滤规则类.class)
              })
@Configuration//相当于配置文件
public class ApplicationConfig {

}

此外还需配置过滤规则类。

2.2、将指定类排除Spring容器外

将指定类排除Spring容器外使用excludeFilters

@ComponentScan(value="com.luis.beans",
               excludeFilters={
                       @Filter(type=FilterType.ANNOTATION,
                               value={Controller.class,Service.class})
               })
@Configuration//相当于配置文件
public class ApplicationConfig {

}

3、@Conditionnal注解

@Conditionnal是Spring提供的注解,用在配置类中,用于动态决定是否添加进Spring容器中。

现有两个类:Student和Teacher

//如果当前工程运行在Windows系统下,就注册Student
public class Student {}

//如果当前工程运行在Linux系统下,就注册Teacher
public class Teacher {}

定义两个判断类:LinuxCondition和WindowsCondition

public class LinuxCondition implements Condition {
    /*
     * ConditionContext context:spring容器上下文环境
     * AnnotatedTypeMetadata metadata :@Conditional修饰类型信息
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
          String systemName = context.getEnvironment().getProperty("os.name");
          if(systemName.contains("Linux")){
              return true;
          }
          return false;
    }
}
public class WindowsCondition implements Condition {

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
           String systemName = context.getEnvironment().getProperty("os.name");
           if(systemName.contains("Windows")){
               return true;
           }
        return false;
    }
}

配置类代码:

@Configuration//相当于配置文件
public class ApplicationConfig {

    @Conditional({LinuxCondition.class})
    @Bean
    public Teacher teacher(){
        return new Teacher();
    }

    @Conditional({WindowsCondition.class})
    @Bean
    public Student student(){
        return new Student();
    }
}

4、@Import注解

用来组合多个配置类, 相当于spring配置文件中的import标签,在引入其他配置类时,可以不用再写@Configuration 注解。也可以指定将指定bean导到SpringIOC容器中

@import(value="com.luis.Student")
@Configuration//相当于配置文件
public class ApplicationConfig {

}

此外,可通过自定义的选择器将bean添加到IOC容器中。

public class MyImportSelector implements ImportSelector {

    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        String classNames[]={"com.luis.Student"};
        return classNames;
    }
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //1.将Java类注册到Spring
        BeanDefinitionBuilder builer  = BeanDefinitionBuilder.genericBeanDefinition(Teacher.class);
        //2.创建当前Java类的实例对象
        BeanDefinition obj= builer.getBeanDefinition();

        //3.通过Spring的bean注册器,将当前Java类的实例对象添加到Spring容器
        registry.registerBeanDefinition("luis", obj);
    }
}

配置类代码如下:

@Import(value={MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
@Configuration//相当于配置文件
public class ApplicationConfig {
    //两种添加方式
}

5、FactoryBean接口

FactoryBean是Spring容器提供的一种注册bean的方式,通过它来获得组件的bean的对象以及bean对象的单例或则多例的形态。

public class MyFactoryBean implements FactoryBean<Student> {

    //通知Spring容器,当前Student类的实例对象创建方式
    public Student getObject() throws Exception {
        return new Student();
    }

    //通知Spring容器,被管理的bean对象在spring容易对应的类型
    public Class<?> getObjectType() {
        return Student.class;
    }

    /*
     *   true 单例
     *   false prototype
     * */
    public boolean isSingleton() {
        return true;
    }
}

配置类代码如下:

@Configuration//相当于配置文件
public class ApplicationConfig {
    @Bean
     public FactoryBean factoryBean(){
         return new MyFactoryBean();
     }
}

6、@PropertySource注解

写在配置类中,用于 加载properties配置文件,相当于context:property-placeholder标签

properties文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring
jdbc.username=root
jdbc.password=root

配置类:

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 创建一个数据源,并存入 spring 容器中
     */
    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

二、bean对象赋值

1、@Value注解

@Value可在当前类中指定属性上赋值,其有以下几种用法:

public class Student {

    @Value("luis")//使用基本数据为属性赋值
    private String sname;
    @Value("#{28-2}")//使用SPEL为属性赋值
    private int age;
    @Value("${student.home}")//读取来自于外部的properties属性文件内容
    private String home;
}

2、BeanPostProcessor

为所有的类的指定属性赋值BeanPostProcessor(后置处理器),BeanPostProcessor接口的自定义直接实现类可以在当前Spring容器的 所有bean对象初始化前后被调用。

BeanPostProcessor是一个接口,主要用于在bean对象初始化前后,做一些辅助功能

其中,postProcessBeforeInitialization:bean被初始化之前工作,postProcessAfterInitialization:被初始化之后工作

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    //在bean对象初始化之前被调用 bean是Spring容器管理一个对象,beanName就是当前对象在Spring容器关联关键字
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        if(bean.getClass()==Dog.class){
          try{
              Field field = bean.getClass().getDeclaredField("age");
              field.setAccessible(true);
              field.set(bean, 15);
          }catch(Exception ex){
              ex.printStackTrace();
          }
        }else if(bean.getClass()==Bird.class){
             try{
                  Field field = bean.getClass().getDeclaredField("age");
                  field.setAccessible(true);
                  field.set(bean, 9);
              }catch(Exception ex){
                  ex.printStackTrace();
              }
        }
        return bean;
    }

    //在bean对象初始化之后被调用 bean是Spring容器管理一个对象,beanName就是当前对象在Spring容器关联关键字
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

配置类:

@ComponentScan(value={"com.luis.beans"})
@Configuration//相当于配置文件
public class ApplicationConfig {}

BeanPostProcessor的原理是:遍历Spring容器中所有的BeanPostProcessor,执行每一个BeanPostProcessor中的 postProcessBeforeInitialization方法,如果某一次执行返回null.则立刻结束执行。

三、Bean的生命周期

1、@Bean注解处理Bean

可以在类文件中定义初始化或销毁方法,通过@Bean注解进行方法的指定。

public class Student{
    public void init() {
        System.out.println("对象被创建");
    }

    public void destory() {
        System.out.println("对象被回收");
    }
}
@Configuration//相当于配置文件
public class ApplicationConfig {
     @Bean(initMethod="init",destoryMethod="destory")
    public Student student(){
        return new Student();
    }
}

2、InitializingBean&DisposableBean

我们可以让类文件同时实现InitializingBean接口与DisposableBean接口,根据这两个接口提供的监听方法来监听当前类的bean的实例化时机和销毁时机。

public class Student implements InitializingBean, DisposableBean {

    public Student() {
        System.out.println("Student构造方法被调用");
    }

    public void destroy() throws Exception {
        System.out.println("Student对象被销毁");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("Student对象被初始化");
    }
}

3、@PreDestroy& @PostConstruct

可以在类中指定方法上添加这两个注解,来指定监听bean对象被实例化和销毁的时机。这两个注解不是由Spring提供的。

public class Student{

    public Student() {
        System.out.println("Student构造方法被调用");
    }

    @PreDestroy
    public void destroy() throws Exception {
        System.out.println("Student对象被销毁");
    }

    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        System.out.println("Student对象被初始化");
    }
}

四、Junit的使用

在进行单元测试的过程中,每个方法都需要创建上下文容器,他们是不可或缺的,但又与我们的只写业务代码的理念相违背,不过好在Junit 给我们暴露了一个注解(@RunWith),可以让我们替换掉它的运行器。这时,我们需要依靠 spring 框架,因为它提供了一个运行器,可以读取配置文件(或注解)来创建容器,使用时只要指出配置文件的位置。其步骤如下:

  • 添加依赖包:spring-test
  • 通过@RunWith注解,指定spring的运行器,Spring的运行器为:SpringJunit4ClassRunner
  • 过@ContextConfiguration注解,指定spring运行器需要的配置文件路径
  • 通过@Autowired注解给测试类中的变量注入数据

示例代码如下:

示例代码如下:

```java

@RunWith(SpringJunit4ClassRunner.class)

@ContextConfiguration(locations="classpath:applicationContext.xml")

public calss TestStudentService{

@Autowired

private StudentMapper studentMapper;

@Test
public void getStudent(){
    studentMapper.getStudent();
}

}

原文地址:https://www.cnblogs.com/liuyi6/p/10217108.html

时间: 2024-09-30 05:45:10

Spring基于纯注解方式的使用的相关文章

阶段3 2.Spring_10.Spring中事务控制_8 spring基于纯注解的声明式事务控制

新建项目 把之前项目src下的内容全部复制过来 pom.xml内复制过来 开始配置 新建一个config的包,然后再新建配置文件类SpringConfiguration @Configuration这个注解是可写可不写的. 这个类会做为字节码的参数传给ApplicationContext @ComponentScan配置要扫描的包 @Import 但是这个Import要导谁呢? 新建JdbcConfig类 这一就可以通过Import导入JdbcConfig这个类 xml里面扫描包的配置可以省略掉

spring与hibernate整合配置基于Annotation注解方式管理实务

1.配置数据源 数据库连接基本信息存放到properties文件中,因此先加载properties文件 1 <!-- jdbc连接信息 --> 2 <context:property-placeholder 3 location="classpath:io/shuqi/ssh/spring/transactionalAnnotation/jdbc.properties"/> 使用DBCP数据源配置xml如下 1 <!-- dbcp数据源配置 -->

Spring文档苦读【6】【纯注解方式配置MVC】

前言 Spring官方文档提供纯注解方式进行配置,无需XML,只需要相关的JAVA类即可实现项目的注册以及容器的管理. 注解XML <web-app> <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext --> <context-param> <param-n

「spring」定时任务(纯注解方式)

[问题现象] 需要通过纯注解方式启动定时任务,网上搜索到的定时任务大部分都是配置+注解. [问题解决] /** * 定时任务:打印CPU使用率 */@Component@EnableSchedulingpublic class PrintCpuWorker {    @Scheduled(cron="0/10 * *  * * ? ") // 每10秒一次    public void print() {        System.out.println("PrintCpu

spring AOP自定义注解方式实现日志管理

转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在applicationContext-mvc.xml中要添加的 <mvc:annotation-driven />     <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->     <conte

一个简单的Spring定时器例子 注解方式

首先在applicationContext.xml中增加 文件头中增加一条 xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation 中增加一条 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd <beans xmlns:task=&quo

springmvc3.2+spring+hibernate4全注解方式整合(四)

以上是工程文件,下面开始测试 package test.testservice; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.t

springmvc3.2+spring+hibernate4全注解方式整合(一)

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.

springmvc3.2+spring+hibernate4全注解方式整合(三)

service接口 package com.fangjian.core.platform.service; import com.fangjian.core.platform.po.User; public interface UserService { void saveUser(User user); } service实现 package com.fangjian.core.platform.service.impl; import org.springframework.beans.fa