关联文章:
Spring注解驱动开发-组件注册(一)
Spring注解驱动开发-生命周期(二)
Spring注解驱动开发-属性赋值&自动装配(三)
Spring注解驱动开发-AOP(四)
@Data@AllArgsConstructor@NoArgsConstructor
public class Person {
@Value("小红") //第一种方式赋值
private String name;
@Value("#{20-2}") //第二种方式
private int age;
@Value("${person.nickNamee}") //第三种方式
private String nickName;
}
配置类:
使用@PropertySource读取外部配置文件中的k/v保存到运行环境变量中
加载完外部配置文件后就可以用${}取值
//使用@PropertySource读取外部配置文件中的k/v保存到运行环境变量中
//加载完外部配置文件后就可以用${}取值
@PropertySource(value = { "classpath:person.properties" })//可以写多个配置文件
@Configuration//这是一个配置类==配置文件
public class ManConfigOfProperty {
@Bean
public Person person() {
return new Person();
}
}
测试
@Test
public void test1() throws Exception {
//1.创建IOC容器
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ManConfigOfProperty.class);
System.out.println("容器创建完成...");
Person bean = ac.getBean(Person.class);
System.out.println(bean);
System.out.println("=====================");
ConfigurableEnvironment environment = ac.getEnvironment();
String property = environment.getProperty("person.nickNamee");
System.out.println(property);
}
}
结果
容器创建完成...
Person(name=小红, age=18, nickName=小张三)
=====================
小张三
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zxc.service.EmployeeService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
5.@Primary:让Spring进行自动装配的时候,默认使用首选bean,也可以继续使用@Qualifier指定要装配的bean名字
service:
@Service
@Getter@Setter
public class EmployeeService {
private int label = 1;
@Override
public String toString() {
return "EmployeeService [label=" + label + "]";
}
}
controller:
@Controller
public class EmployeeController {
@Qualifier("employeeService2")
@Autowired
private EmployeeService employeeService;
@Override
public String toString() {
return "EmployeeController [employeeService=" + employeeService + "]";
}
}
配置类:
@Configuration
@ComponentScan({"com.zxc.service","com.zxc.controller"})
public class MainConfigOfAutowired {
@Bean("employeeService2")
public EmployeeService employeeService() {
EmployeeService employeeService = new EmployeeService();
employeeService.setLabel(2);
return employeeService;
}
}
测试
@Test
public void test1() throws Exception {
//1.创建IOC容器
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
System.out.println("容器创建完成...");
EmployeeController bean = (EmployeeController) ac.getBean("employeeController");
System.out.println(bean);
Object bean2 = ac.getBean("employeeService");
System.out.println(bean2);
}
输出:
容器创建完成...
//使用了@Qualifier指定了注入的对象
EmployeeController [employeeService=EmployeeService [label=2]]
EmployeeService [label=1]
@Resource:
和@Autowired一样实现自动装配,默认按照组件名称进行装配。没有支持@Primary和@Autowired(required=false)功能
@Inject:
需要导入javax.inject的包,和@Autowired功能一样,没有required=false的功能
AutowiredAnnotationBeanPostProcessor :解析完成自动装配功能
1).标注在构造器上 如果组件只有一个有参构造器,@Autowired可以省略,参数位置的组件可以自动注入
2).标注在方法上 直接标注在set方法上或者@Bean+方法参数,参数从容器自动注入(默认不写,也可以自动装配)
3).标注在参数上
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory)
自定义组件实现xxxAware,在创建对象的时候会调用接口规定的方法注入相关的组件
xxxAware:功能使用xxxProcessor 比如ApplicationContextAware==>ApplicationContextAwareProcessor(后置处理器)
实现几个常见的Aware接口:
public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware{
@Override //Embedded 植入的,深入的,内含的
public void setEmbeddedValueResolver(StringValueResolver stringvalueresolver) {
String stringValue = stringvalueresolver.resolveStringValue("解析字符串"+"${os.name} "+"#{10*10}");
System.out.println(stringValue);
}
@Override
public void setBeanName(String s) {
System.out.println("当前Bean的名字:"+s);
}
@Override
public void setApplicationContext(ApplicationContext applicationcontext) throws BeansException {
System.out.println("传入的IOC:"+applicationcontext);
}
}
注入到Ioc容器后测试结果:
当前Bean的名字:com.zxc.bean.Red
解析字符串Windows 10 100
传入的IOC:org.springframework.context.annotation.AnnotationConfigApplicationContext@11028347: startup date [Mon Mar 04 20:16:52 CST 2019]; root of context hierarchy
原理:
Debug定位到ApplicationContextAwareProcessor.postProcessBeforeInitialization()方法
public Object postProcessBeforeInitialization(final Object bean, String beanName)
throws BeansException
{
AccessControlContext acc = null;
if(System.getSecurityManager() != null && ((bean instanceof EnvironmentAware) || (bean instanceof EmbeddedValueResolverAware) || (bean instanceof ResourceLoaderAware) || (bean instanceof ApplicationEventPublisherAware) || (bean instanceof MessageSourceAware) || (bean instanceof ApplicationContextAware)))
acc = applicationContext.getBeanFactory().getAccessControlContext();
if(acc != null)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run()
{
invokeAwareInterfaces(bean);
return null;
}
final Object val$bean;
final ApplicationContextAwareProcessor this$0;
{
this.this$0 = ApplicationContextAwareProcessor.this;
bean = obj;
super();
}
}, acc);
else
invokeAwareInterfaces(bean);
return bean;
}
调用下面方法进行判断
private void invokeAwareInterfaces(Object bean)
{
if(bean instanceof Aware)
{
if(bean instanceof EnvironmentAware)
((EnvironmentAware)bean).setEnvironment(applicationContext.getEnvironment());
if(bean instanceof EmbeddedValueResolverAware)
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(embeddedValueResolver);
if(bean instanceof ResourceLoaderAware)
((ResourceLoaderAware)bean).setResourceLoader(applicationContext);
if(bean instanceof ApplicationEventPublisherAware)
((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(applicationContext);
if(bean instanceof MessageSourceAware)
((MessageSourceAware)bean).setMessageSource(applicationContext);
if(bean instanceof ApplicationContextAware)
((ApplicationContextAware)bean).setApplicationContext(applicationContext);
}
}
profile:侧面,半面; 外形,轮廓
Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能
二种方式指定(激活)环境:
-Dspring.profiles.active=test
例子:
开发环境,测试环境,生产环境
数据源:(/A)(/B)(/C)
配置类:
@Configuration // 配置类==配置文件
public class MainConfig_Profile implements EmbeddedValueResolverAware {
@Value("${jdbc.username}")
private String userName;
private String url;
@Profile("test")
@Bean("testDateSource")
public DataSource DataSourceTest(@Value("${jdbc.password}") String password) {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl(url);
ds.setPassword(password);
ds.setUsername(userName);
return ds;
}
@Profile("dev")
@Bean("devDateSource")
public DataSource DataSourceDevelopMent(@Value("${jdbc.password}") String password) {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl(url);
ds.setPassword(password);
ds.setUsername(userName);
return ds;
}
@Override // Embedded 植入的,深入的,内含的
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String resolveStringValue = resolver.resolveStringValue("${jdbc.url}");
this.url = resolveStringValue;
}
}
测试:
注意 :使用无参构造器创建一个applicationContext,我们设置环境后自己注册配置类,有参就走下面流程了
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
this();
register(annotatedClasses); //注册配置类
refresh();
}
@Test
public void test1() throws Exception {
// 1.使用无参构造器创建一个applicationContext
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
// 2.设置需要激活的环境
ac.getEnvironment().setActiveProfiles("test");
// 3.注册配置类
ac.register(MainConfig_Profile.class);
// 4. 启动刷新容器
ac.refresh();
// 获取容器中的bean名称打印
String[] definitionNames = ac.getBeanDefinitionNames();
for (String string : definitionNames) {
System.out.println(string);
}
}
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig_Profile
testDateSource