Spring框架

Spring框架也被称为Spring容器。其作用是将创建和管理对象的操作都交给这个容器进行,这样在项目中就不需要再关心这个过程,直接在容器中拿来使用即可。

在开发中,若是多个类都依赖于同一个类,在各自创建这个类时,就会产生多个相同的类,这违背了“只需要一个”的思想。

若是需要Spring来管理对象,就需要先创建对象,在Spring中创建并被Spring管理的对象被称为Spring bean

创建对象的方式有两种,组件扫描和@Bean方法

通过@Bean注解创建对象,首先需要在类上添加@configuration注解,其次在方法上添加@Bean注解 列如:

@Configuration
public class SpringConfig{
    @Bean
    public Random random(){
        return new Random();
    }
}

//测试代码
public class SpringRunner {
        public static void main(String[] args) {
        // 1. 加载Spring
        AnnotationConfigApplicationContext ac
        = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 2. 从Spring中获取对象
        Random random = (Random) ac.getBean("random");
        // 3. 测试使用对象,以便于观察是否获取到了有效的对象
        System.out.println("random : " + random);
        // 4. 关闭
        ac.close();
    }
}

在上述代码之中,应该知道的是,AnnotationConfigApplicationContext(ACAC)中的构造方法,需要将SpringConfig.class作为参数传入,这样可以让该类中的内容进行加载。@Configuration注解虽不是必要,但是在使用时为了规范,还是应在类上加上注解。
在getBean中传入的参数是@Bean方法的名称。@Bean是必须添加的注解,只有添加之后这个方法才会被Spring调用,并管理此方法的返回结果
在getBean方法中添加不同的参数重载

//在此方法中,传入的参数必须是有效的,不然会有NoSuchBeanDefinitionException异常
Object getBean(String beanName);
//在此方法中,传入的类型有且仅有一个对象,如果没有,那么会出现NoSuchBeanDefinitionException异常
//若是有两个及以上,会导致NoUniqueBeanDefinitionException异常
T getBean(Class<T>beanClass);
//上面两个方法的综合
T getBean(String beanName,Class<T>beanClass);

若是在@Bean注解后传一个String类型的参数时,在调用getBean方法时,填入的beanName就应该是@Bean后的参数。列如
 

@Configuration
public class SpringBeanFactory {
    @Bean("random")
    public Random random1() {
        return new Random();
    }
}

public class SpringRunner {
        public static void main(String[] args) {
        // 1. 加载Spring
        AnnotationConfigApplicationContext ac
        = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 2. 从Spring中获取对象
        //此时@Bean注解后加了参数,所以在getBean方法中传的参数不是方法名,而是参数的值
        Random random = (Random) ac.getBean("random");
        // 3. 测试使用对象,以便于观察是否获取到了有效的对象
        System.out.println("random : " + random);
        // 4. 关闭
        ac.close();
    }
}

  组件扫描,通过在类上加@Component、@Controller、@Service、@Repository,使其称为组件类。接着在另一个类上加@Configuration注解成为配置类,再添加@componentScan(包名),去扫描这个包下的组件类。

package cn.tedu.spring;
@Component
public class UserMapper {
}

package cn.tedu.spring;
@Configuration
@ComponentScan("cn.tedu.spring")//这里传入的值为组件类的所在包的包名
public class SpringConfig {
}

//若是输入的包名为cn 那么在扫描时就会扫描cn下所有包中存在的组件类

在扫描组件类调用getBean获取对象时,传入的是组件类名首字母改成小写的字符串

package cn.tedu.spring;
@Component
public class UserMapper {
}

package cn.tedu.spring;
@Configuration
@ComponentScan("cn.tedu.spring")
public class SpringConfig {
}


public class SpringRunner {
    public static void main(String[] args) {
        // 1. 加载Spring
        AnnotationConfigApplicationContext ac
        = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 2. 从Spring中获取对象
        UserMapper userMapper = ac.getBean("userMapper", UserMapper.class);
        // 3. 测试使用对象,以便于观察是否获取到了有效的对象
        System.out.println("userMapper :" + userMapper);
        // 4. 关闭
        ac.close();
    }
}

在创建AnnotationConfigApplicationContext对象时,传入的参数SpringConfig类添加了组件扫描的注解,所以Spring回去扫描配置的包,在包中的组件类都会被Spring框架创建组件类对象去管理,
若是组件类不在该包中,则Spring框架不会知道此类的存在,若是无此注解,也不会创建此类的对象。
在getBean中传入的类名参数,若是类名第一个字母大写,第二个字母小写,则传入的参数为首字母小写,若是不符合这种情况,那么传入的就应该是与类名完全相同的字符串

若是在@Component后添加参数,与@Bean一样,在调用getBean方法时传入的值就应该是注解后面的参数
 

@Component("userMapperBean")
public class UserMapper {
}
//beanName为UserMapperBean而不是userMapper

通过@Bean或组件扫描的方式创建对象的区别,使用@Bean方法创建,需要Spring管理的对象越多,则添加的@Bean方法也越多,但是这样可以自定义创建对象的过程。通过组建扫描只需要配置一次,然后各类组件类添加组件即可,各组件类添加注解之后也能增加可读性,但组件扫描的方法只能只用与自定义的类。

Spring Bean的作用域,在默认的情况下是单例的,在程序运行的过程中,每个类的对象最多只能有一个,并且常驻在内存之中,在ApplicationContext调用销毁方法后,或者程序结束运行结束后销毁。

通过在@Bean方法上加@Scope注解,或者在组件类注解上加上@Scope注解,可以改变作用域
 

@Configuration
public class SpringBeanFactory {

    @Scope("prototype")//在@Bean方法上添加@Scope注解并填入prototype,可以让作用域变为非单例
    //prototype:原型:非单例
    @Bean
    public Random random(){
        return new Random();
    }
}
//在@Scope中填入singleton值,即添加的是默认值,与不配置@Scope是相同的效果,该实例仍为唯一
//singletion:单例的
@Scope("singleton")
@Repository
public class UserMapper{

}

懒加载:@Lazy,在@Bean方法声明前或者早组件类声明前添加@Lazy注解可以使对象在被使用使才创建出来。Spring默认为预加载,在添加懒加载注解时,由于注解的value默认为ture,直接添加注解便可时对象成为懒加载对象

预加载和懒加载相比:预加载可以在程序运行时就会创建出来,可以直接使用,但若是需要创建管理的对象太多,就会使程序启动变慢,并且许多没用到的类,会造成资源浪费,懒加载相比于预加载,在对象被使用时才会创建并存储到内存中,但是在系统负荷较大时,再创建对象,会对系统产生更大的负担。

自动装配机制:在Spring中,拥有自动装配机制,其机制使用的注解为@Autowired注解,当一个属性添加了该注解,那么Spring会尝试在容器中找到一个合适的值去为这个类赋值。

@Configuration
@ComponentScan("cn.tedu.spring")
public class SpringConfig {
}


@Repository 
public class UserMapper {

    public void insert() {
        System.out.println("UserMapper.insert()");
    }

}

@Controller
public class UserController {

    @Autowired(required = false)
    public UserMapper mapper;

    public void reg() {
        System.out.println("UserController.reg()");
        mapper.insert();
    }

}

public class SpringRunner04 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac
                = new AnnotationConfigApplicationContext(SpringConfig.class);

        UserController userController = (UserController) ac.getBean("userController");

        userController.reg();

        ac.close();
    }

}

从上图代码中可以看见,在加载SpringConfig类是,根据配置类上的组件扫描注解去寻找组件类,并将这些组件类创建好对象保存在容器中,在UserController类中使用了@Autowired注解,而注解下的UserMapper类是组件类,所以Spring会为该属性赋值。于是在UserController中的mapper可以调用UserMapper中的insert()方法,并最终在控制台输出文本。

IoC:(Inversion of Control) 控制反转 是Spring框架的核心,即将创建对象,赋值,管理对象的作用域和生命周期等全部交给Spring去完成。

DI:(Dependency Injection) 依赖注入,是Spring框架实现IoC的核心实现。在一个类中声明了另一个类的属性,即为依赖,Spring会帮开发者完成依赖项的赋值。

在Spring中通过DI来实现IoC,所以DI是完成IoC这一目标的重要手段。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值