本文介绍的内容如下
Java注入:@Configuration、@Bean
自动注入:
XML:<component-scan/>
Java:@ComponentScan
@Repository
@Service
@Controller
@Component
Profile:
Java:@Profile
XML:<beans profile="dev"
条件注解:
@Conditional
Bean的生命周期:
singleton、prototype、request、session
混合配置:
@ImportResource
Java配置
Java配置本质上,就是使用一个Java类去代替xml配置,这种配置方式在SpringBoot中得到了广泛的使用。
1、引入的依赖及相关类
2、创建实体类并创建getset方法
public class Book {
private Integer id;
private String name;
private String author;
}
3、创建java配置类
import org.springframework.context.annotation.Bean;
/**
* 这个是Java配置类,它的作用类似于applicationContext.xml文件
*/
public class JavaConfig {
/**
* 返回一个JavaBean的方法就类似于applicationContext.xml中的一个bean标签
*
* <bean class="com.itbaizhna.Book" id="book"></bean>
* @return
* 默认情况下,id就是方法名,可以通过@Bean注解的value或者name属性自定义方法名
*/
@Bean(name = "b1")
Book book(){
return new Book();
}
}
4、在入口方法处,加载Java配置
import org.junit.Before;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 使用AnnotationConfigApplicationContext可以实现
* 基于Java的配置类加载Spring的应用上下文.避免使用application.xml进行配置。
* 在使用spring框架进行服务端开发时,个人感觉注解配置在便捷性,和操作上都优于是使用XML进行配置;
*/
public class Test {
private AnnotationConfigApplicationContext ctx;
@Before
public void before(){
ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
}
@org.junit.Test
public void test1() {
Book book = (Book) ctx.getBean("book");
System.out.println(book);
Book book1 = ctx.getBean(Book.class);
System.out.println(book1);
}
//在JavaConfig中添加@Bean(name = "b1")
@org.junit.Test
public void test2() {
Book b1 = (Book) ctx.getBean("b1");
System.out.println(b1);
}
}
自动配置
前面这种配置方式,对于所有要使用的类都需要一个一个的配置。可以通过自动配置来简化Bean的配置。
XML配置实现
1、引入的依赖以及相关类
2、创建user实体类并创建getset方法,重写tostring方法
import org.springframework.stereotype.Component;
/**
* @Component注解表示该类是一个bean,在项目启动时,该类会被自动扫描,
* 然后实例化并注册到Spring容器中去,实例默认的名字就是类名首字母小写
*
* 类似的注解,Spring一共提供了四个:
* 1. @Component,一般用在身份不明确的组件上
* 2. @Service,一般用在Service层
* 3. @Controller,一般用在控制层
* 4. @Repository,一般用在数据库访问层
*
* 但是,目前来说,这四个的功能基本一致,没有大的区别
*/
@Component
public class User {
private Integer id;
private String name;
private String address;
}
创建person实体类
package com.tang.bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
* Person的注解为@Component的时候,xml中只要有
* <bean class="com.tang.bean.Person" id="p" scope="prototype"/>就能执行
*
* Person的注解为@Service("p")的时候,xml中只要有
* <context:component-scan base-package="com.tang.bean"/>就能运行
*/
//@Component
@Service("p")
public class Person {
public void sayHello(String name){
System.out.println("hello"+name);
}
}
3、创建xml配置类,标准写法可以进行包的精确扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--可以在com.tang.bean后面加“,”,添加其他的-->
<context:component-scan base-package="com.tang.bean"/>
<!--<context:component-scan base-package="com.tang.bean ,com.tang.ser"/>-->
<bean class="com.tang.bean.Person" id="p" scope="prototype"/>
<!--标准写法-->
<!--并且只响应了service的,没有响应Component的,所以会导致使用Component注解的用不了-->
<!--<context:component-scan base-package="com.tang" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>-->
</beans>
4、在入口方法处,加载XML配置
import com.tang.bean.Person;
import com.tang.bean.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class main {
private ClassPathXmlApplicationContext ctx;
@Before
public void before() {
ctx = new ClassPathXmlApplicationContext("application.xml");
}
//使用标准写法后执行报错
@Test
public void test1() {
User user = (User) ctx.getBean("user");//user要小写
System.out.println(user);
}
//使用标准写法后
@Test
public void test2() {
Person p = (Person) ctx.getBean("p");
p.sayHello("zhangsan");
}
}
Java配置和XML配置基本一致,唯一不同的地方就是包扫描的方式。
四个注解是一样的。
包扫描通过@ComponentScan来实现:
创建Java配置类,标准写法可以进行包的精确扫描
@Configuration//@Configuration用于定义配置类,可替换xml配置文件
//@ComponentScan(value = "com.tang.bean")简单写法
@ComponentScan(value = "com.tang.bean", useDefaultFilters = false, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class)
})
public class JavaConfig {
}
然后再Main中引用java配置就可以了
Profile配置
在实际开发中,项目即将上线时,可能需要不停的在开发环境、生产环境、测试环境...之间进行切换。
数据库配置:url,username,password
redis:地址
mongodb:地址、用户名、密码
...
...
1、引入的依赖以及相关类
2、创建相应的实体类
public class DateSource {
private String url;
private String username;
private String password;
}
public class RedisConfig {
private String url;
private String password;
}
3、创建java配置类
import com.tang.bean.DateSource;
import com.tang.bean.RedisConfig;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Service;
@Configuration//@Configuration用于定义配置类,可替换xml配置文件
@ComponentScan(value = "com.tang.bean", useDefaultFilters = false, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class)
})
public class JavaConfig {
/**
* @return
* @Profile注解相当于一个标记,标记当前的dataSource是开发环境下的dataSource
*/
@Bean("ds")
@Profile("dev")
DateSource devDs() {
return new DateSource("jdbc:mysql:///dev", "dev", "dev");
}
@Bean("ds")
@Profile("prod")
DateSource prodDs() {
return new DateSource("jdbc:mysql://123.99.88.77:3306/prod", "prod", "prod");
}
@Bean("rc")
@Profile("dev")
RedisConfig devRc() {
return new RedisConfig("127.0.0.1", "123");
}
@Bean("rc")
@Profile("prod")
RedisConfig prodRc() {
return new RedisConfig("123.33.44.55", "jflakjdkla");
}
}
测试类 注意这里的顺序问题,需要首先设置当前环境,然后再去加载配置类。
import com.tang.bean.DateSource;
import com.tang.bean.RedisConfig;
import com.tang.config.JavaConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class test1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
//设置当前环境为开发环境(dev)
ctx.getEnvironment().setActiveProfiles("dev");
ctx.register(JavaConfig.class);
ctx.refresh();
DateSource ds = (DateSource) ctx.getBean("ds");
System.out.println(ds);
RedisConfig rc = (RedisConfig) ctx.getBean("rc");
System.out.println(rc);
}
}
结果
DateSource{url='jdbc:mysql:///dev', username='dev', password='dev'}
RedisConfig{url='127.0.0.1', password='123'}
4、创建xml配置类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd">
<beans profile="dev">
<bean class="com.tang.bean.DateSource" name="ds">
<property name="username" value="root"/>
<property name="password" value="123"/>
<property name="url" value="jdbc:mysql:///123123213"/>
</bean>
</beans>
<beans profile="prod">
<bean class="com.tang.bean.DateSource" name="ds">
<property name="username" value="prod"/>
<property name="password" value="prod"/>
<property name="url" value="jdbc:mysql:///dev"/>
</bean>
</beans>
</beans>
测试类 注意,beans标签要写在其他标签的后面。使用步骤和Java配置类似:
import com.tang.bean.DateSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test2 {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles("prod");
ctx.setConfigLocation("applicationContext.xml");
ctx.refresh();
DateSource ds = (DateSource) ctx.getBean("ds");
System.out.println(ds);
}
}
结果
DateSource{url='jdbc:mysql:///dev', username='prod', password='prod'}
条件注解
Profile实际上就是条件注解的一种特殊形式,即条件注解更加灵活,用户可以根据各种不同的条件使用不同的Bean。
条件注解在SpringBoot中使用非常广泛。SpringBoot中提供了许多自动化的配置,例如数据库配置,SpringBoot使用条件注解提前配置好许多常用的类,使用条件注解,在某一个条件满足时,这些配置就会生效。
1、引入的依赖以及相关类
2、定义接口
public interface ShowCmd {
String show();
}
3、创建相关的实体类实现接口
public class WinShowCmd implements ShowCmd{
@Override
public String show() {
return "Ws";
}
}
public class LinuxShowCmd implements ShowCmd {
@Override
public String show() {
return "Ls";
}
}
4、定义条件
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class WinCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = conditionContext.getEnvironment().getProperty("os.name");
return osName.toLowerCase().contains("window");
}
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = conditionContext.getEnvironment().getProperty("os.name");
return osName.toLowerCase().contains("linux");
}
}
5、在java中配置Bean
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan(value = "com.tang")
public class JavaConfig {
@Bean("cmd")
@Conditional(WinCondition.class)
ShowCmd win() {
return new WinShowCmd();
}
@Bean("cmd")
@Conditional(LinuxCondition.class)
ShowCmd linux() {
return new LinuxShowCmd();
}
}
6、使用
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(JavaConfig.class);
ctx.refresh();
ShowCmd cmd = (ShowCmd) ctx.getBean("cmd");
String show = cmd.show();
System.out.println(show);
}
}
7、结果
Ws
Bean的作用域
bean的作用域有四种,常用的有两种:
1.prototype,每次请求,都是一个新的Bean
2.singleton,bean是单例的
3.request,在一次请求中,bean的声明周期和request同步
4.session,bean的生命周期和session同步
在spring的配置中,默认情况下,bean都是单例的(singleton)。无论获取多少次,获取到的都是同一个bean。修改为prototype。
定义方式如下:
@Component
@Scope(value = "prototype")
public class User {
private Integer id;
private String name;
private String address;
}
在xml中配置方式如下:
<bean class="com.itbaizhan.bean.Person" id="p" scope="prototype"/>
@Test
public void test1() {
User user = (User) ctx.getBean("user");//user要小写
User user2 = (User) ctx.getBean("user");
System.out.println(user==user2);
System.out.println(user);
}
加上这个后,创建的两个user对象就是不同的了
混合配置
混合配置就是XML配置+Java配置
在混合配置中,主要通过如下注解向Java配置中导入XML配置:
@ImportResource(locations = "classpath:applicationContext.xml")