Spring大略学习
Posted JunMain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring大略学习相关的知识,希望对你有一定的参考价值。
Spring大略学习(一)
7. Bean的自动装配
什么是自动装配?
Spring会根据上下文自动寻找,自动给bean装配属性
自动装配的方式
Spring有三种装配方式
- xml中显示配置
- java中显示配置
- 隐式 的自动装配bean 【重点】
1. byName自动装配
当bean的id的名字跟java类的属性名一致的时候,就会调用set注入赋值
People
package com.lzj.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People
private String name;
private Dog dog;
<bean id="People" class="com.lzj.entity.People" p:name="先驱" autowire="byName"/>
<bean id="dog" class="com.lzj.entity.Dog">
<property name="name" value="大欢"/>
<property name="size" value="18"/>
</bean>
<bean id="dog2" class="com.lzj.entity.Dog">
<property name="name" value="大黄"/>
<property name="size" value="29"/>
</bean>
这边会吧id="dog"的注入到属性
2. byType自动装配
会根据bean的class自动装配,但是有一个坏处,出现两个同样类型的属性时无法注入,需要用byName
Dog
package com.lzj.entity;
import lombok.Data;
@Data
public class Dog
private String name;
private String size;
People
package com.lzj.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People
private String name;
private Dog dog;
注入
<bean id="People" class="com.lzj.entity.People" p:name="先驱" autowire="byType"/>
<bean id="Dog" class="com.lzj.entity.Dog">
<property name="name" value="大欢"/>
<property name="size" value="18"/>
</bean>
test
@Test
public void test01()
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println((People)context.getBean("People"));
但是当有两条狗名字id不一样的时候
<bean id="People" class="com.lzj.entity.People" p:name="先驱" autowire="byType"/>
<bean id="Dog1" class="com.lzj.entity.Dog">
<property name="name" value="大欢"/>
<property name="size" value="18"/>
</bean>
<bean id="Dog2" class="com.lzj.entity.Dog">
<property name="name" value="大黄"/>
<property name="size" value="29"/>
</bean>
package com.lzj.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People
private String name;
private Dog dog;
这个时候我们在利用byType注入属性就会报错
不知道应该注入哪一个
3. 注解自动装
导入约束。搭建环境
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解的支持 -->
<context:annotation-config/>
</beans>
@Autowired
是spring的注解,可以使用在属性 、set、构造器中, 是通过内部byType的方式注入。
当放在javaBean的属性 (引用的时候)如果bean里面有该类型,会自动注入
其实不需要set方法也可以使用@Autowired来实现ref类的注入,底层通过反射可以获取类的任何东西,包括private
所以有无setXXX()方法不影响
xml配置
<bean id="Dog" class="com.lzj.entity.Dog">
<property name="name" value="大欢"/>
<property name="size" value="18"/>
</bean>
<bean id="cat" class="com.lzj.entity.Cat">
<property name="name" value="猫猫"/>
</bean>
<bean id="animal" class="com.lzj.entity.Animal"/>
Animal
package com.lzj.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
@Data
public class Animal
@Autowired
private Dog dog1;
@Autowired
private Cat cat1;
test
@Test
public void test01()
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println((Animal)context.getBean("animal"));
注:@Autowired(required=false)放在属性上表示当在Spring容器里面找不到该类对象的时候不会报错,允许为null
@Autowired + @Qualifier 的组合
由于@Autowired是byType的,当有两个一样的bean类型,但是id不一样的时候,就会出现问题,于是就有@Qualifier
在举一个Dog1 Dog2的例子
Dog
package com.lzj.entity;
import lombok.Data;
@Data
public class Dog
private String name;
private String size;
xml
<bean id="People" class="com.lzj.entity.People" p:name="先驱" autowire="byType"/>
<bean id="Dog1" class="com.lzj.entity.Dog">
<property name="name" value="大欢"/>
<property name="size" value="18"/>
</bean>
<bean id="Dog2" class="com.lzj.entity.Dog">
<property name="name" value="大黄"/>
<property name="size" value="29"/>
</bean>
Animal
package com.lzj.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
@Data
public class Animal
@Autowired
private Dog dog1;
这个时候由于Autowired是byType的,但是此时容器里面有两个Dog的实例对象,这个时候就会不知道该注入哪一个从而报错
这个时候需要用@Qualifier来指定到底选哪一个Dog
package com.lzj.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@Data
public class Animal
@Autowired
@Qualifier("Dog1")
private Dog dog1;
test
@Test
/**
* 测试@Autowired的弊端,需要加@Qualifier
*/
public void test02()
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println((Animal) context.getBean("animal"));
@Resource
是java的内部注解 可以使用在属性 、set、构造器中
优先byType, 冲突byName
King
package com.lzj.entity;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import javax.annotation.Resource;
@ToString
public class King
@Value("大不列颠") //通过@Value注入普通类型
private String name;
@Resource
private Wife wife;
Wife
package com.lzj.entity;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
@ToString
public class Wife
@Value("伊丽莎白") //通过@Value注入普通类型
private String name;
xml
<bean id="animal" class="com.lzj.entity.Animal"/>
<bean id="Wife" class="com.lzj.entity.Wife"/>
<bean id="king" class="com.lzj.entity.King"/>
test
@Test
/**
* 测试@Resource
* 例子:King, Wife
*/
public void test03()
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println((King)context.getBean("king"));
这边我们发现无论Wifebean的id怎么改,都能正确的注入,@Resource是先按照byName如果name不符合再byType
4. 存在的问题
属性的循环依赖问题
Boy的属性依赖 Girl
package com.lzj.entity;
import lombok.Data;
@Data
public class Boy
private String name;
private Girl girl;
Girl的属性依赖Boy
package com.lzj.entity;
import lombok.Data;
@Data
public class Girl
private String name;
private Boy boy;
我们单个从Spring容器中获取Boy, Girl对象的时候没有任何问题,
但是我们一旦利用自动注入为其属性赋值的时候就出现了的时候就出现问题了(栈溢出错误)
<bean id="girl" class="com.lzj.entity.Girl"
autowired="byType">
<property name="name" value="sm"/>
</bean>
<bean id="boy" class="com.lzj.entity.Boy" autowired="byType">
<property name="name" value="lzj"/>
</bean>
public void test01()
ApplicationContext context= new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println((Boy)context.getBean("boy"));
8. 使用注解开发
环境配置
确保aop的包导入
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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解的支持 -->
<context:annotation-config/>
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package=Spring大略学习