spring注解驱动开发笔记

目录

1.@scope 

2.@conditional注解,分条件加载bean

    总结:给容器中注册组件:

3.bean的生命周期

    3.1:自定义初始化和销毁方法,在容器对bean进行生命周期处理的时候调用我们自己的初始化,销毁方法

    3.2:实现implements InitializingBean, DisposableBean接口来初始化和销毁bean对象

    3.3:使用JSR250规范中的两个注解

    3.4:使用BeanPostProcessor

4.spring的@value注解

    4.1:括号中写具体的数值

    4.2:使用SpEL表达式

    4.3:使用$符号

5.@PropertySource加载配置属性源,然后使用@value设置数据

6.@ConfigurationProperties

7.自动注入

    7.1:@Autowired--spring注解

    7.3:@Resource---java规范注解

    7.4:使用@Inject---java规范注解

8:aware注入spring底层组件及其原理

9.从配置文件读取配置文件

10:使用@Profile根据环境注册对应的组件



看到有和我一样看了该视频总结的博友,喜欢的可以去看看

https://blog.youkuaiyun.com/DeepClouds/article/details/105903727?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

1.@scope 

    singleton:单例模式,ioc容器创建的时候就会调用这个方法创建对象放在容器中,下次获取就是从容器中直接获取

    单例模式也可以实现不在ioc容易启动的时候创建bean,使用@Lzay实现懒加载,也可以在获取的时候创建对象,且仅仅会创建一次,不管你获取几次,并且获取几次的bean都是一样的,区别于多例模式每次获取每次都创建,多次获取的bean不相同.

    prototype:多例模式,ioc容器启动不会创建,获取的时候才会创建出来,而且没每次获取都会创建,所以每次获取的对象不相同.

2.@conditional注解,分条件加载bean

linux的同样写法,条件不一样而已,这只是简单的演示,context中还能获取其他组件能帮助根据条件加载bean.如果@conditional加在类上面就是整个类的配置都生效.

    总结:给容器中注册组件:

  1:包扫描+组件标注注解(@Controller,@Service,@Repository,@Component)

  2.使用@Bean,写在方法上,返回一个组件对象

  3.@Import({多个需要导入了大类}) 写在类上面,id默认是全类名

  4.@Import配合ImportSelector来注册bean

     4.1.使用@Import引入我们自定义的MyImportSelector,例如:@Import({MyImportSelector.class})

     4.2. 定义MyImportSelector,实现ImportSelector,实现里面的selectImports方法,方法返回一个String数组,数组里面就是我们要导入的类的全类名.例如:return new String[]{"com.alimm.model.Apple","com.alimm.model.Pear"},这样就能注册到spring中.

   5.使用ImportDefinitionRegistrar,实现registerBeanDefinitions方法,

  6. 使用FctoryBean来注册bean对象

package com.honeypeng.factory;

import com.honeypeng.entity.Employee;
import org.springframework.beans.factory.FactoryBean;

public class MyFactory implements FactoryBean<Employee> {
    //获取到某个bean
    @Override
    public Employee getObject() throws Exception {
        return new Employee();
    }

    //获取到bean类型
    @Override
    public Class<?> getObjectType() {
        return Employee.class;
    }

    //是否单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

3.bean的生命周期

    3.1:自定义初始化和销毁方法,在容器对bean进行生命周期处理的时候调用我们自己的初始化,销毁方法

        2.1.1:如果是配置文件的方式,我们就需要在<Bean>配置中加上 init-method和destory-method

        2.1.2:如果是使用注解@Bean的方式也一样使用 @Bean(initMethod = "init",destroyMethod = "destory"),init和destory就是在bean对象中我们自己定义的初始化和销毁方法.

    @Bean(initMethod = "init",destroyMethod = "destory")
    public Employee employee(){
        return new Employee();
    }

如果是单实例bean,容器会在启动的时候创建,初始化,然后容器关闭的时候销毁 application.close()的时候关闭.

如果是多实例bean,会在获取的时候创建bean,并且初始化,但是不会帮忙销毁bean.

    3.2:实现implements InitializingBean, DisposableBean接口来初始化和销毁bean对象

package com.honeypeng.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;

/**
 * Created by jx on 2018/9/16.
 */
public class Pig implements InitializingBean, DisposableBean {

    private String name;

    private Integer Age;

    public Pig(){
        System.out.println(this.getClass().getName()+"  Constructor ");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return Age;
    }

    public void setAge(Integer age) {
        Age = age;
    }

    private void init() {
        System.out.println(this.getClass().getName() + "  +++++init()...");
    }

    private void destory() {
        System.out.println(this.getClass().getName() + "  +++++destory()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(this.getClass().getName() + " +++++afterPropertiesSet....");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " +++++destroy...");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println(this.getClass().getName()+"  +++++postConstruct");
    }
}

从这里可以看出执行顺序是:  构造方法(设置好值后)>@PostConstruct> initializingBean的afterPropertiesSet方法 > bean对象中自己定义的init()初始化方法.(使用@Bean(initMethod = "init",destroyMethod = "destory"))

 顺序如下:Constructor > @PostConstruct > InitializingBean > init-method

 然后bean的销毁先后顺序是:disposableBean的Destory方法>> 自定义的destory方法(@Bean(initMethod = "init",destroyMethod = "destory"))

    3.3:使用JSR250规范中的两个注解

          @PostConstract(在bean创建完之后且属性赋值完成,来执行该方法)

          @PreDstory(在容器销毁bean对象之前执行该方法)

package com.honeypeng.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * Created by jx on 2018/9/16.
 */
public class Pig implements InitializingBean, DisposableBean {

    private String name;

    private Integer Age;

    public Pig(){
        System.out.println(this.getClass().getName()+"  Constructor ");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return Age;
    }

    public void setAge(Integer age) {
        Age = age;
    }

    private void init() {
        System.out.println(this.getClass().getName() + "  +++++init()...");
    }

    private void destory() {
        System.out.println(this.getClass().getName() + "  +++++自定义的destory()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(this.getClass().getName() + " +++++afterPropertiesSet....");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " +++++ DisposableBean.destroy...");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println(this.getClass().getName()+"  +++++postConstruct");
    }
    @PreDestroy
    public void preDestory() {
        System.out.println(this.getClass().getName()+"  +++++preDestory");
    }
}

执行结果是:

可以看得出来顺序是  preDestory>>disposableBean的distory方法>>自定义的destory方法

    3.4:使用BeanPostProcessor

         postProcessBeforeInitialization:在属性赋值和所有的初始化操作之前,无论是@PostConstruct > InitializingBean > init-method中的任何一个初始化方法之前执行

         postProcessAfterInitialization:在所有的初始化操作之后执行,无论是@PostConstruct > InitializingBean > init-method中的任何一个之后执行.

4.spring的@value注解

    可以使用@value设置属性值,通常有下面三种使用方法

    4.1:括号中写具体的数值

          比如:@Value("张三")

    4.2:使用SpEL表达式

        @Value("#{20/2}")

    4.3:使用$符号

        @Value("${配置文件中配置的数值}")

5.@PropertySource加载配置属性源,然后使用@value设置数据

6.@ConfigurationProperties

    当我们需要直接将配置文件中的数据映射设置到自己建好的对象中,就可以使用这个注解,@ConfigurationProperties(prefix = "person")

配置文件:

person:
    lastName: hello
    age: 18
    boss: false
    birth: 2017/12/12
    maps: {k1: v1,k2: 12}
    lists:
      - lisi
      - zhaoliu
    dog:
      name: 小狗
      age: 12

7.自动注入

    7.1:@Autowired--spring注解

        现根据类型注入,如果多个,再根据名称注入

        BookDao bookDao;现根据BookDao这个类型注入,然后根据bookDao这个名称;如果没有就会报错,可以使用

required = false来处理,当有多个类型的Dao我们可以使用@Qualifier来指定具体的某个Dao对象.当有多个Dao我们又没有指定,我们想优先加载某个Dao对象,那么可以在创建这个Dao的地方加上@Primary注解,表示优先加载这个Dao,这里仅仅使用Dao来举例,其他要注入的对象使用原则一致

    @Autowired使用范围

        1).使用在属性上,我们经常用的

         2):使用在构造方法上

这样获取回来的dog对象是spring容器中的对象

      3)使用在参数列表上面

 

    7.3:@Resource---java规范注解

       1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

        不支持@primary,没有@autowired(required=false)的功能

    7.4:使用@Inject---java规范注解

      需要导入javax.inject包,和Autowird功能一样,能支持@Primary,只是没有required=false的功能.

8:aware注入spring底层组件及其原理

     自定义的组件想使用spring底层的组件,比如说applicationContext,beanFactory都有对应的aware接口,我们自定义的组件实现我们想使用的spring底层组件对应的aware接口就行了.

     比如我想使用一下ApplicationContext,就需要实现ApplicationContextAware接口,然后实现里面的setApplicationContext方法,设置ApplicationContext就行了.

     原理:通过断点我们可以看到进入到了ApplicationContextAwareProcessor的postProcessBeforeInitialization方法中,该类实现了

BeanPostProcessor,这个我们都知道是在初始化前后做一些操作的.然后进去invokeAwareInterfaces方法中,可以看到调用了setApplicationContext方法,invokeAwareInterfaces中的bean参数就是我们自定义组件对象,也就是实现ApplicationContextAware接口的对象,我这里是pig对象,所以就是调用pig对象中的setApplicationContext方法.

9.从配置文件读取配置文件

    使用@propertySource("classpath:***.properties")指定数据源

    9.1:在属性上面我们使用@Value("${配置文件的字段}")

    9.2:在参数列表上面使用@Value("${配置文件的字段}")

    9.3:配置文件类实现EmbeddedValueResoleverAware接口,实现setEmbeddedValueResolver,注入resolver;调用resolver.resolverStringValue("${配置文件中的字段}")方法来解析数据.获取配置文件

10:使用@Profile根据环境注册对应的组件

 

/**
 * Profile:
 * 		Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
 * 
 * 开发环境使用A数据源、测试环境使用B数据源、生产环境使用C数据源;
 * 
 * 
 * @Profile:指定组件在哪个环境的情况下才能被注册到容器中,如果不指定,任何环境下都能注册这个组件:例如Yellow组件
 * 
 * 1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
 * 2)、如果@Profile写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
 * 3)、没有标注环境标识的bean在,任何环境下都是加载的;
 */

@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile /**从配置文件获取数据方式3*/implements EmbeddedValueResolverAware{
	
    //从配置文件获取数据方式1
	@Value("${db.user}")
	private String user;
	
	private StringValueResolver valueResolver;
	
	private String  driverClass;
	
	
	@Bean
	public Yellow yellow(){
		return new Yellow();
	}
	
	@Profile("test")//测试环境才设置这个数据源
	@Bean("testDataSource")
	public DataSource dataSourceTest(/**从配置文件获取数据方式2*/@Value("${db.password}")String pwd) throws Exception{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser(user);
		dataSource.setPassword(pwd);
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
		dataSource.setDriverClass(driverClass);
		return dataSource;
	}
	
	
	@Profile("dev")//开发环境设置这个数据源
	@Bean("devDataSource")
	public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser(user);
		dataSource.setPassword(pwd);
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");
		dataSource.setDriverClass(driverClass);
		return dataSource;
	}
	
	@Profile("prod")//生产环境设置这个数据源
	@Bean("prodDataSource")
	public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser(user);
		dataSource.setPassword(pwd);
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515");
		
		dataSource.setDriverClass(driverClass);
		return dataSource;
	}

    //从配置文件获取数据方式3,解析配置文件中的值
	@Override
	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		// TODO Auto-generated method stub
		this.valueResolver = resolver;
		driverClass = valueResolver.resolveStringValue("${db.driverClass}");
	}

}

    测试激活环境方式:

      1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test,在下面图片idea中配置jvm运行参数


      2、代码的方式激活某种环境;例如下面激活的是dev的环境

    //1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
	//2、代码的方式激活某种环境;
	@Test
	public void test01(){
		AnnotationConfigApplicationContext applicationContext = 
				new AnnotationConfigApplicationContext();
		//1、创建一个applicationContext
		//2、设置需要激活的环境
		applicationContext.getEnvironment().setActiveProfiles("dev");
		//3、注册主配置类
		applicationContext.register(MainConfigOfProfile.class);
		//4、启动刷新容器
		applicationContext.refresh();
		
		
		String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
		for (String string : namesForType) {
			System.out.println(string);
		}
		
		Yellow bean = applicationContext.getBean(Yellow.class);
		System.out.println(bean);
		applicationContext.close();
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值