在 xml 中可以指定 标签中的 primary 属性为 true ,跟上面标注 @Primary 注解是一样的。
另外可以修改注入对象的变量名:
4.3.5 @Autowired注入的原理逻辑
先拿属性对应的类型,去 IOC 容器中找 Bean ,如果找到了一个,直接返回;如果找到多个类型一样的 Bean , 把属性名拿过去,跟这些 Bean 的 id 逐个对比,如果有一个相同的,直接返回;如果没有任何相同的 id 与要注入的属性名相同,则会抛出NoUniqueBeanDefinitionException异常。
优先级:类型 -> id
4.3.6 多个相同类型Bean的全部注入
注入一个用单个对象接收,注入一组对象就用集合来接收。
如上就可以实现一次性把所有的 Person 都注入进来。
4.3.7 自动注入的规范:JSR250-@Resource
JSR 全程 Java Specification Requests ,它定义了很多 Java 语言开发的规范,有专门的一个组织叫 JCP ( Java Community Process ) 来参与定制。
public class WithAnnoApplication {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("basic_dl/quickstart-withanno.xml");
Map<String, Object> beans = ctx.getBeansWithAnnotation(Color.class);
beans.forEach((beanName, bean) -> {
System.out.println(beanName + " : " + bean.toString());
});
}
}
public class BeannamesApplication {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("basic_dl/quickstart-withanno.xml");
String[] beanNames = ctx.getBeanDefinitionNames();
// 利用jdk8的Stream快速编写打印方法
Stream.of(beanNames).forEach(System.out::println);
}
}
public class LazyLookupApplication {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("basic_dl/quickstart-lazylookup.xml");
Cat cat = ctx.getBean(Cat.class);
System.out.println(cat);
// 下面的代码会报Bean没有定义 NoSuchBeanDefinitionException
// Dog dog = ctx.getBean(Dog.class);
// 这一行代码不会报错
ObjectProvider<Dog> dogProvider = ctx.getBeanProvider(Dog.class);
// 只有调用 dogProvider 的 getObject ,真正要取包装里面的 Bean 时,才会报异常
dogProvider.getObject()
}
}
Dog dog = dogProvider.getIfAvailable();
if (dog == null) {
dog = new Dog();
}
Dog dog = dogProvider.getIfAvailable(() -> new Dog());
// 或者
Dog dog = dogProvider.getIfAvailable(Dog::new);
// 或者
dogProvider.ifAvailable(dog -> System.out.println(dog)); // 或者使用方法引用
@Configuration
public class QuickstartConfiguration {
}
@Bean
public Person person() {
return new Person();
}
@Bean(name = "aaa") // 4.3.3之后可以直接写value
public Person person() {
return new Person();
}
public class AnnotationConfigApplication {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new AnnotationConfigApplicationContext(QuickstartConfiguration.class);
Person person = ctx.getBean(Person.class);
System.out.println(person);
}
}
@Bean
public Person person() {
Person person = new Person();
person.setName("person");
person.setAge(123);
return person;
}
@Bean
public Cat cat() {
Cat cat = new Cat();
cat.setName("test-cat-anno");
// 直接拿上面的person()方法作为返回值即可,相当于ref
cat.setMaster(person());
return cat;
}
@Configuration
// 顺便加上包扫描
@ComponentScan("com.linkedbear.spring.basic_di.c_value_spel.bean")
@PropertySource("classpath:basic_di/value/red.properties")
public class InjectValueConfiguration {
}
@Component
public class White {
@Value("#{blue.name.substring(0, 3)}")
private String name;
@Value("#{T(java.lang.Integer).MAX_VALUE}")
private Integer order;
}
@Component
public class Person {
private String name = "administrator";
// setter
}
@Component
public class Dog {
@Value("dogdog")
private String name;
private Person person;
// toString() ......
}
@Component
public class Dog {
// ......
@Autowired
private Person person;
}
@Component
public class Dog {
// ......
private Person person;
@Autowired
public Dog(Person person) {
this.person = person;
}
}
@Component
public class Dog {
// ......
private Person person;
@Autowired
public void setPerson(Person person) {
this.person = person;
}
}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.linkedbear.spring.basic_di.d_autowired.bean.Person' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
@Autowired(required = false)
private Person person;
Dog{name='dogdog', person=null}
@Configuration
@ComponentScan("com.linkedbear.spring.basic_di.d_complexfield.bean")
public class InjectComplexFieldConfiguration {
@Bean
@Autowired // 高版本可不标注
public Cat cat(Person person) {
Cat cat = new Cat();
cat.setName("mimi");
cat.setPerson(person);
return cat;
}
}
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.linkedbear.spring.basic_di.d_complexfield.bean.Person' available: expected single matching bean but found 2: administrator,master
@Autowired
@Qualifier("administrator")
private Person person;
@Bean
@Primary
public Person master() {
Person master = new Person();
master.setName("master");
return master;
}
@Autowired
private Person administrator;
@Component
public class Dog {
// ......
@Autowired
private List<Person> persons;
}
@Component
public class Bird {
@Resource(name = "master")
private Person person;
}
@Component("miaomiao")
public class Cat {
private String name = "cat";
}
@Component
public class Person2 {
@Value("#{new String[] {'张三', '张仨'}}")
private String[] names;
@Value("#{{'333333', '3333', '33'}}")
private List<String> tels;
// 引用现有的Bean,以及创建新的Bean
@Value("#{{@miaomiao, new com.linkedbear.spring.basic_di.g_complexfield.bean.Cat()}}")
private Set<Cat> cats;
@Value("#{{'喵喵': @miaomiao.name, '猫猫': new com.linkedbear.spring.basic_di.g_complexfield.bean.Cat().name}}")
private Map<String, Object> events;
@Value("#{{'123': '牵着手', '456': '抬起头', '789': '我们私奔到月球'}}")
private Properties props;
}
public interface Aware {
}
public class AwaredTestBean implements ApplicationContextAware {
private ApplicationContext ctx;
public void printBeanNames() {
Stream.of(ctx.getBeanDefinitionNames()).forEach(System.out::println);
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.ctx = ctx;
}
}
public class AwaredTestBean implements ApplicationContextAware, BeanNameAware {
private String beanName;
private ApplicationContext ctx;
public String getName() {
return beanName;
}
public void printBeanNames() {
Stream.of(ctx.getBeanDefinitionNames()).forEach(System.out::println);
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.ctx = ctx;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
}
@Component
public class Dog {
private Person person;
@Autowired
public void setPerson(ObjectProvider<Person> person) {
// 有Bean才取出,注入
this.person = person.getIfAvailable();
}
}
@Component
public class Dog {
private Person person;
@Autowired
public Dog(ObjectProvider<Person> person) {
// 如果没有Bean,则采用缺省策略创建
this.person = person.getIfAvailable(Person::new);
}
}
public class Child {
// 当前的小孩子想玩球
private String wantToy = "ball";
public String getWantToy() {
return wantToy;
}
public abstract class Toy {
private String name;
public Toy(String name) {
this.name = name;
}
}
public class Ball extends Toy { // 球
public Ball(String name) {
super(name);
}
}
public class Car extends Toy { // 玩具汽车
public Car(String name) {
super(name);
}
}
public class ToyFactoryBean implements FactoryBean<Toy> {
@Override
public Toy getObject() throws Exception {
return null;
}
@Override
public Class<Toy> getObjectType() {
return Toy.class;
}
}
public class ToyFactoryBean implements FactoryBean<Toy> {
private Child child;
@Override
public Toy getObject() throws Exception {
// 根据 Child 中的 wantToy 属性,来决定创建哪个玩具:
switch (child.getWantToy()) {
case "ball":
return new Ball("ball");
case "car":
return new Car("car");
default:
// SpringFramework2.0开始允许返回null
// 之前的1.x版本是不允许的
return null;
}
}
@Override
public Class<Toy> getObjectType() {
return Toy.class;
}
public void setChild(Child child) {
this.child = child;
}
}
@Bean
public Child child() {
return new Child();
}
@Bean
public ToyFactoryBean toyFactory() {
ToyFactoryBean toyFactory = new ToyFactoryBean();
toyFactory.setChild(child());
return toyFactory;
}