配置形式:基于XML文件的方式、基于注解的方式、基于java的配置
Bean的配置方式:通过全类名(反射)、通过工厂方法、FactoryBean
IOC容器:BeanFactory、ApplicationContext
Bean的注入方式:属性Set注入、构造器注入、工厂方法注入(不推荐)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean name="c" class="com.nchu.pojo.Category">
<property name="name" value="category 1" />
bean>
<bean name="p" class="com.nchu.pojo.Student">
<property name="name" value="leihuihuanhg"/>
<property name="sid" value="16206119"/>
<property name="category" ref="c"/>
<property name="son" ref="s"/>
bean>
<bean name="s" class="com.nchu.pojo.Son">
<property name="sid" value="1" />
bean>
beans>
// Java测试类文件
public static void main(String[] args) {
//1. 创建 Spring 的 IOC 容器对象
// ApplicationContext代表IOC容器
// ClassPathXmlApplicationContext:是ApplicationContext 接口的实现类。该实现类从类路径下加载配置文件。
//
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "applicationContext.xml" });
//2. 从 IOC 容器中获取Bean 实例
// 直接通过bean的id来定位到IOC容器中的bean
Category c = (Category) context.getBean("c");
// 通过类型来读取 ( 要求bean在IOC容器中是唯一的 )
Category c2 = (Category) context.getBean(Category.class);
//3. 调用Category中对象方法
System.out.println(c.getName());
System.out.println(c2.getName());
}
}
自动装配:
byType和ByName
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8WcrgNab-1570415559250)(C:\Users\Leisure\AppData\Roaming\Typora\typora-user-images\1569237296261.png)]
<bean name="c" class="com.nchu.pojo.Category">
<property name="name" value="category 1" />
bean>
2.1 静态工厂方法:
<constructor-arg value="大的"> constructor-arg>
bean>
// 静态工厂类:直接调用某一个类的静态方法就可以返回Bean实例
public class InstanceSonFactory {
private static Map<String,Son> sons = new HashMap<String,Son>();
// 使用静态工厂方法配置bean
static {
sons.put("大的",new Son(1,"男"));
sons.put("小的",new Son(2,"女"));
}
// 使用静态方法返回对应的实例
public static Son getSon(String name){
return sons.get(name);
}
}
2.2 实例工厂方法:
bean>
<bean id="son1" factory-bean="son" factory-method="getSon">
<constructor-arg value="小的"> constructor-arg>
bean>
// 实例工厂类
public class InstanceSonFactory {
private Map<String,Son> sons = null;
//实例工厂方法:即需要创建工厂本身,再调用工厂的实例方法来返回bean的实例
// 使用实例工厂方法配置bean
public InstanceSonFactory(){
sons = new HashMap<String,Son>();
sons.put("大的",new Son(1,"男"));
sons.put("小的",new Son(2,"女"));
}
public Son getSon(String name){
return sons.get(name);
}
}
XML文件:
<property name="brand" value="好的">property>
bean>
Java文件:
// 自定义的factoryBean需要实现 FactoryBean 接口
public class SonFactoryBean implements FactoryBean{
private String brand;
// 使用getObject方法来返回bean实例
@Override
public Son getObject() throws Exception {
// TODO Auto-generated method stub
return new Son(20,"男");
}
// 返回实例的类型
@Override
public Class getObjectType() {
// TODO Auto-generated method stub
return Son.class;
}
//返回是否是单例的
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return true;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
1. 继承
<bean id="student1" parent="student">
<property name="name" value="hui">property>
bean>
<bean id="student" abstract="true" class="com.nchu.pojo.Student">
<property name="name" value="lei">property>
<property name="age" value="20">property>
<property name="sid" value="16206119">property>
<property name="son" ref="son">property>
<property name="category" ref="c">property>
bean>
<bean id="student" abstract="true">
bean>
2. 依赖
Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好
如果前置依赖于多个 Bean,则可以通过逗号,空格方式配置 Bean 的名称
scope: singleton(默认)、prototype、session、request。
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
Set()属性注入
<bean name="p" class="com.nchu.pojo.Student">
<property name="name" value="leihuihuanhg"/>
<property name="sid" value="16206119"/>
<property name="category" ref="c"/>
<constructor-arg ref="s"/>
<property name="s.price" value="250"/>
<property name="c1">
<bean class="com.nchu.pojo.Category">
<constructor-arg value="lei" type="String">constructor-arg>
<constructor-arg value="16206119" index="1">constructor-arg>
bean>
property>
bean>
<bean name="c" class="com.nchu.pojo.Category">
<property name="name">
<list>
<ref bean="c1"/>
list>
property>
<property name="id">
<map>
<entry key="11" value="BB">entry>
map>
property>
bean>
<bean id="c20" class="com.nchu.pojo.Category" p:name="lei20"/>
bean>
构造器注入
<bean name="c1" class="com.nchu.pojo.Category">
<constructor-arg value="lei" type="Java.lang.String">constructor-arg>
<constructor-arg index="1">
<value>16206119value>
constructor-arg>
<constructor-arg index="2">
<value>]]>value>
constructor-arg>
bean>
工厂方法注入:静态工厂方法注入、实例工厂方法注入
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dateSource" class="com.asjf2.DataSource">
<property name="user" value="${user}">property>
<property name="password" value="${password}">property>
<property name="driverClass" value="${driverUrl}">property>
<property name="jdbcUrl" value="${jdbcUrl}">property>
bean>
//外部属性文件 "db.properties"
user=root
password=1234
driverclass=com.mysql.jdbc.Driver
jdbcurl=jdbc:mysql:///test
Spring 表达式语言**(简称SpEL):是一个支持运行时查询和操作对象图**的强大的表达式语言。
语法:
#{…} 作为限定符,大括号里面的字符就是SpEL
实现功能:
例子:
<property name=“name” value="#{'Chuck'}"/> 或
<property name='name' value='#{"Chuck"}'/>
<bean id="student" class="com.nchu.pojo.Student">
<property name="age" value="20">property>
<property name="score" value="#{T(java.lang.Math).PI * 80}"/>
<property name="son" value="#{son}">property>
<property name="sid" value="#{son.sid}">property>
<property name="name" value="#{son.sex == '男' ? ' 雷' : '辉煌'}">property>
<property name="category" ref="c">property>
bean>
@Component // 基本注解,标识这是一个受Spring管理的组件
@Respository //标识持久层组件
@Service //标识服务层(业务层)组件
@Controller //标识控制(表现层)层的注解
//注意:可以混用,但是最好不要
//这几个注解并没有任何功能上的区别,你可以把这些当做是分类标签,目的是为了让你的代码可读性更强
// 第一个字母进行小写,也可以在注解中通过 value 属性值标识组件的名称
UserService =>> userService
@Controller(value="uc")
或
@Controller("uc")
在组件类上使用特定的注解
在配置文件中声明**context:component-scan**
<context:component-scan base-package="com.nchu" use-default-filters="true" resource-pattern="Service/*.class">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:exclude-filter type="assignable" expression="com.nchu.repository.UserRespository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
context:component-scan>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S4WDzXNj-1570415559252)(C:\Users\Leisure\AppData\Roaming\Typora\typora-user-images\1569479016314.png)]
context:component-scan元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有**@Autowired 和@Resource** 、@Inject注解的属性。三个注解用法相似。
@Autowired
自动装配具有兼容类型的单个Bean属性
构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
@Autowired(required=false)
private UserService userService;
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
@Autowired(required=false)
@Qualifier("userService")
private UserService userService;
// 直接用于方法上
public void setUserService(@Qualifier("userService") UserService userService){
System.out.println(111111);
}
@Authwired 注解也可以应用在数组类型、集合、java.util.Map 的属性上。
Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用,泛型基类的引用关系能够被实现类继承。
**作用:**可以节省大量代码,提高开发效率。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GlQAxWRA-1570415559253)(C:\Users\Leisure\AppData\Roaming\Typora\typora-user-images\1569485691978.png)]
// 基类服务层
public class BaseService<T> {
@Autowired
protected BaseRespository<T> respository;
public void add(){
System.out.println("add....");
System.out.println(respository);
}
}
// 基类持久层
public class BaseRespository<T> {
}
// 实现类持久层
@Repository
public class UserRepository extends BaseRespository<User> {
}
// 实现类服务层
@Service
public class UserService extends BaseService<User>{
}
**同名bean:**多个bean 有相同的 name 或者 id,称之为同名bean
的id 和 name的区别:
id和name都是spring 容器中bean 的唯一标识符。
id: 一个bean的唯一标识,命名格式必须符合XML ID属性的命名规范
name: 可以用特殊字符,并且一个bean可以用多个名称:name=“bean1,bean2,bean3” ,用逗号或者分号或者空格隔开。如果没有id,则name的第一个名称默认是id。
spring 容器如何处理同名bean?
同一个spring配置文件中,bean的 id、name是不能够重复的,否则spring容器启动时会报错。
如果一个spring容器从多个配置文件中加载配置信息,则多个配置文件中是允许有同名bean的,并且后面加载的配置文件的中的bean定义会覆盖 前面加载的同名bean。
spring 容器如何处理没有指定id、name属性的bean?
如果 一个 标签未指定 id、name 属性,则 spring容器会给其一个默认的id,值为其类全名。
如果有多个 标签未指定 id、name 属性,则spring容器会按照其出现的次序,分别给其指定 id 值为 “类全名#1”, “类全名#2” … L
Spring自带了多种类型的应用上下文。
1 | ⭐AnnotationConfigApplicationContext | 从一个或多个基于Java的配置类中加载Spirng应用上下文 |
---|---|---|
2 | AnnotationConfigWebApplicationContext | 从一个或多个基于Java的配置类中加载Spring Web应用上下文。 |
3 | ⭐ClassPathXmlApplicationContext | 从类路径下的一个或多个XMl配置文件中加载上下文定义,把应用上下文的定义文件作为资源 |
4 | ⭐FileSystemXmlApplicationContext | 从文件系统下的一个或多个XML配置文件中加载上下文定义 |
5 | XmlWebApplicationContext | 从Web应用下的一个或多个XMl配置文件中加载上下文定义 |
//1.从Java配置中加载配置,将Bean装载到应用上下文。
ApplicationContext context=new AnnotationConfigApplicationContext(com.springaction.knights.config.KnightConfig.class);
示例:
public void launchByAnnotationConfigApplicationContext(){
// 使用AnnotationConfigApplicationContext来配置Bean
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Bean_dog.class,BeanConfiguration.class);
// 装配bean中的对象
Dog dog = applicationContext.getBean(Dog.class);
Person person = applicationContext.getBean(Person.class);
System.out.println(dog.getName());
System.out.println(person);
// 返回对于指定类型Bean(包括子类)的所有名字
String[] namesForType = applicationContext.getBeanNamesForType(Dog.class);
for (String name : namesForType) {
System.out.println(name);
}
}
//1.从类路径下读取配置文件,将Bean装载到应用上下文。
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
示例:
public void launchByClassPathXmlApplicationContext(){
// 使用ClassPathXmlApplicationContext来配置bean
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
// 装配bean中的对象
Person person = (Person)ac.getBean("person");
System.out.println(person);
}
//1.从文件系统读取配置文件,将Bean装载到应用上下文。
ApplicationContext context=new FileSystemXmlApplicationContext("D:/applicationContext.xml");
示例
public void launchByFileSystemXmlApplicationContext(){
// 使用ClassPathResource来配置bean
ApplicationContext ac = new FileSystemXmlApplicationContext("D:\\git-workspace\\ssm-in-action\\spring-in-action\\src\\main\\resources\\beans.xml");
// 装配bean中的对象
Person person = (Person)ac.getBean("person");
System.out.println(person);
}
//从类路径下读取配置文件
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
示例
public void launchByBeanFactory(){
// 使用ClassPathResource来读取配置文件
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
Dog bean = (Dog) beanFactory.getBean("dog");
System.out.println(bean.getName()+bean.getAge());
}
应用上下文准备就绪之后,我们就可以调用上下文的getBean()方法(beanFactory)从Spring容器中获取bean.
@Autowired
User user;
使用**@Autowired** 时需要使用**@Component**来对应
@Component
public class User {
private Long id;
private String name;
private Integer age;
}