maven工程依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
</dependencies>
1,@Configuration:相当于application.xml配置文件 。
2,@bean:相当于xml配置文件的bean标签<bean id="" />。
例:
@Configuration
public class ConfigurationBean {
@Bean
//@Bean(value="poooy")//poooy表示ioc容器中bean的id别名
public Person person() {
return new Person();
}
}
方法的返回值是注入到IOC容器的Bean,方法名是Bean的id值。
@Test
public void bean0() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigurationBean.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
3,@Scope("prototype"):多实例,IOC容器启动并不会去调用方法创建对象放在容器中。只有每次获取时才会调用方法创建对象
@Scope("singleton"):单实例(默认),IOC容器启动就调用方法创建对象,并把对象放到IOC容器中,以后每次获取只是从容器中get。
4,@Lazy(value=true):懒加载,相对于单例来说的,即启动的时候不执行bean初始化,只有获取bean的时候才执行。true开启。
@Configuration
public class ConfigurationBean {
@Bean
@Scope("singleton")
@Lazy(value=true)//懒加载,相对于单例来说,即启动的时候不执行bean初始化,只有获取bean的时候才执行。true开启。
// String SCOPE_SINGLETON = "singleton"; //默认单实例,单实例还会在启动时候执行构造函数
// String SCOPE_PROTOTYPE = "prototype";//多实例是在获取bean的时候初始化
public Person person() {
return new Person();
}
}
5,@ComponentScan:包扫描,只要标注@controller,@Service@Respository@Component这些注解都会被扫描注入到IOC容器中。相当于xml文件中的<context:component-scan base-package="xxxx">
@Service
public class Made {
}
@Component
public class Student {
}
@ComponentScan(basePackages = {"com.wachs.bean.test2"})//这个包下的标签有@Service等会被注入到IOC
public class PersonConfiguration {
@Bean
public Person person() {//该对象会被注入到IOC
return new Person();
}
}
测试
@Test
public void bean0() {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(PersonConfiguration.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String bean : beanDefinitionNames) {
System.out.println(bean);
}
}
6,@Conditional(value= {}):按照一定的条件进行判断,满足条件就给容器中注入bean,否则不注入。当注解作用在类上时和方法上是不一样,类上:只要满足条件,下面的所有的bean才会生效注入。方法上:注解中条件不满足那bean不会生效注入。
@Configuration
public class PersonConfiguration {
@Conditional(value= {MyConditional.class})//当满足我MyConditional类中的条件才会注入下面方法的bean,这是放在方法上的。
@Bean("mynewPerson")//满足的时候才会注入mynewPerson这个bean
public Person person() {
return new Person();
}
}
public class MyConditional implements Condition{//必须实现Condition接口
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");//获取当前系统名
System.out.println(property);
if(property.contains("Windows 7")) {
return true;//满足
}else {
return false;//不满足
}
}
}
从上图,可以清楚的看到是可以获取到bean的。当改变我们的MyConditional返回false时,就不会获取到。
7,@Import({}):向容器中快速的导入一个组件bean,注入id是全类名bean
方式1:
public class Made {
}
public class Student {
}
@Import({Made.class,Student.class})
public class ConfigurationBean {
@Bean
public Person person12() {
return new Person();
}
}
方式2:
实现 interface ImportSelector 接口
public class Teacher{
}
public class MyImportSelector implements ImportSelector{//必须实现ImportSelector接口
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//返回值就是需要导入注册主键的全类名。
return new String[]{"com.wachs.bean.Teacher"};
}
}
//MyImportSelector:自定义路径,返回需要导入的组件。
@Import({Made.class,MyImportSelector.class})
public class ConfigurationBean {
@Bean
public Person person233() {
return new Person();
}
}
结果:
8,@Value和@PropertySource:可以设置属性的值或获取配置文件中的值,当获取配置文件中的值时,一般配@PropertySource这个注解使用。
9,@PropertySource:加载外部配置文件
Color实体类
public class Color {
// @Value("#{20-10}")//spel
// @Value("zhssf")
@Value(value="10011")//设置bean属性的值。
private Integer id;
@Value("${color.name}")//"${}"获取配置文件中的值,配置注解
private String name;
@Override
public String toString() {
return "Color [id=" + id + ", name=" + name + "]";
}
}
Color.properties
color.id=0000299
color.name=zzzsnanyuo
Configuration配置文件
@PropertySource(value="classpath:Color.properties")//一般配合@value注解使用,获取配置文件中的值。
@Configuration
public class ColorConfiguraAutowired {
@Bean
public Color color() {
return new Color();
}
}
结果
10,实现FactoryBean<>接口注册bean,Spring提供的FactoryBean(工厂Bean)默认获取到的是工厂bean调用getObject()创建的对象。要获取工厂bean 本身,要给id前面加一个&,如"&userFactoryBean"。
public class MyFactoryBean implements FactoryBean<Made>{//实现FactoryBean<>
@Override
public Made getObject() throws Exception {
System.out.println(1111111);
return new Made();//返回值Made被加入到IOC中
}
@Override//返回类型
public Class<?> getObjectType() {
return Made.class;
}
@Override//true单实例,false多
public boolean isSingleton() {
return false;
}
}
@Configuration
public class MyConfigFactoryBean {
@Bean("myFactoryBean")
public MyFactoryBean myFactoryBean() {//注册自定义bean工厂
return new MyFactoryBean();
}
}
测试
@Test
public void bean0() {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MyConfigFactoryBean.class);
Object bean = applicationContext.getBean("myFactoryBean");
System.out.println(bean.getClass());//实际上得到的是class com.wachs.bean.Made,是工厂bean调用getObject()创建的对象。
// 要获取工厂bean 本身,要给id前面加一个&,如"&myFactoryBean"
Object bean2 = applicationContext.getBean("&myFactoryBean");//class com.wachs.conditional.MyFactoryBean
System.out.println(bean2.getClass());
}
}
结果:
11,@Autowired,属性注入。是根据类型在IOC容器中找到匹配的bean注入。可以作用的范围:@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})。
作用在方法上:
@Service
public class PersonService {
@Autowired(required=false) //自动装配,为false时,当自动装配的bean不存在不会报错。
private PersonDao personDao;
}
作用在参数上 :@Bean + @Autowired //@Autowired一般是默认不写的。
@Configuration
public class ColorConfiguraAutowired {
// @Bean + @Autowired //@Autowired一般是默认不写的。
@Bean
public PersonController personController(@Autowired Person person) {
PersonController pc=new PersonController();
pc.setPerson(person);
return pc;
}
@Bean
public Person person() {
return new Person();
}
}
11,@Resource注解,自动装配,作用和@Autowired一样,但是@Resource默认通过name属性去匹配bean。
@Service
public class PersonService {
@Resource
private PersonDao personDao;
}
12,@Qualifier:当容器中存在类型相同的多个组件时,可指定装配注入组件的id,不是属性名称,装配之前,必须IOC容器中存在。
@Service
public class PersonService {
// 是按照类型查找的即applicationContext.getBeanNamesForType(PersonService.class);
// 如果找到多个相同类型的组件,会将属性的名称作为组件的id去容器中查找即applicationContext.getBean("personService");
@Autowired//按照类型注入依赖的,
@Qualifier("personDao2")//指定装配注入组件的id,不是属性名称,装配之前,必须IOC容器中存在personDao2
private PersonDao personDao;
}
13,@Primary 如果bean中有该注解时,Spring进行自动装配的时候,会默认使用首选的bean进行自动装配。
@ComponentScan(basePackages = {"com.wachs.service","com.wachs.dao"})
@Configuration
public class ConfigurationBean {
@Bean("personDao2")
@Primary// 如果bean中有该注解时,Spring进行自动装配的时候,会默认使用首选的bean进行自动装配。
public PersonDao personDao() {
return new PersonDao();
}
}
14,@Profile: Spring 提供的可以根据当前环境,动态的激活和切换一系列组件的功能,@Profile指定组件在哪个环境的情况下能被注册到容器中,如果不指定,任何环境下都能注册这个组件。
配置类:
@PropertySource("classpath:c3p0.properties")
@Configuration
//@Profile("dev")//写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才会生效。
public class MyConfiguration {
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.driverClass}")
private String driverClass;
@Value("${jdbc.url}")
private String jdbcUrl;
/**当整个配置类生效的时候,没有标注环境标识@Profile的bean在任何时候都会加载。
* 开发环境数据源
* @return
* @throws Exception
*/
@Profile("dev")//配置在方法上的这个bean-dataSourceDev,只有这个环境dev被激活才能被注册到容器中。
@Bean("dataSourceDev")
public DataSource profileDev() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl(jdbcUrl);
return dataSource;
}
/**
* 测试环境数据源
* @return
* @throws Exception
*/
@Profile("test")
@Bean("dataSourceTest")
public DataSource profileTest() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl("jdbc:mysql:///test");
return dataSource;
}
}
测试类:
激活@Profile注解方式:1,使用命令行动态参数,在虚拟机参数位置加-Dspring.profiles.active=dev。2,使用程序方式applicationContext.getEnvironment().setActiveProfiles("dev")。
方式1:
方式2:
public class SpringProfileTest {
@Test
public void bean0() {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
//把bean组件上有@Profile环境的bean注册到IOC中
applicationContext.getEnvironment().setActiveProfiles("dev");//激活环境,把dev环境下bean注册
//注册配置类
applicationContext.register(MyConfiguration.class);
applicationContext.refresh();
//输出IOC中定义的bean
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String bean : beanDefinitionNames) {
System.out.println(bean);
}
}
}
.