Spring-配置Bean

Spring

配置bean

配置形式:基于XML文件的方式基于注解的方式基于java的配置

Bean的配置方式:通过全类名(反射)、通过工厂方法、FactoryBean

IOC容器:BeanFactoryApplicationContext

Bean的注入方式:属性Set注入构造器注入、工厂方法注入(不推荐)

1、基于XML文件的方式

 

<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)]

1.2 Bean配置方式:

  1. 通过全类名(反射)
 
    <bean name="c" class="com.nchu.pojo.Category">
        <property name="name" value="category 1" />
    bean>
  1. 通过工厂方法(静态工厂方法&实例工厂方法)

    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);
    	}
    }
    
  2. FactoryBean

    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.3 Bean之间的关系:继承、依赖

1. 继承

  • Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置,并不是 元素里的所有属性都会被继承. 比如: autowire, abstract 等.
  • 子 Bean 也可以覆盖从父 Bean 继承过来的配置。
  • 父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板,可以设置 abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean。
  • 可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true
	
	<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 的名称

    
    	
    

1.4 Bean的作用域

scope: singleton(默认)、prototypesessionrequest


	

(3)request:为每一个网络请求创建一个实例,在请求完成以后bean会失效被垃圾回收器回收

(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后bean会随之失效

1.5 Bean注入的方式

  1. 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>
    
  2. 构造器注入

    
    <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>
    
  3. 工厂方法注入:静态工厂方法注入、实例工厂方法注入

1.6 使用外部属性文件

  • Spring 提供了一个 PropertyPlaceholderConfigurerBeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中. 可以在 Bean 配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer属性文件里加载属性, 并使用这些属性来替换变量.
  • Spring 还允许在属性文件中使用 ${propName},以实现属性之间的相互引用。
	
	
	<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

1.7 SpEL

Spring 表达式语言**(简称SpEL):是一个支持运行时查询和操作对象图**的强大的表达式语言。

语法:

#{…} 作为限定符,大括号里面的字符就是SpEL

实现功能:

  • 通过Bean的id对Bean进行引用
  • 调用方法以及引用对象的属性
  • 计算表达式的值
  • 正则表达式匹配

例子:


<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> 

2、基于注解的方式

2.1 特定注解:

@Component // 基本注解,标识这是一个受Spring管理的组件
@Respository 	//标识持久层组件
@Service 		//标识服务层(业务层)组件
@Controller		//标识控制(表现层)层的注解

//注意:可以混用,但是最好不要
//这几个注解并没有任何功能上的区别,你可以把这些当做是分类标签,目的是为了让你的代码可读性更强

2.2 Spring默认命名策略:

// 第一个字母进行小写,也可以在注解中通过 value 属性值标识组件的名称
UserService =>> userService

@Controller(value="uc")@Controller("uc")

2.3 配置步骤:

  1. 在组件类上使用特定的注解

  2. 在配置文件中声明**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>
    
    • base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类,当需要扫描多个包时**,可以使用逗号分隔.
    • resource-pattern 属性仅扫描特定的类而非基包下的所有类,示例:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S4WDzXNj-1570415559252)(C:\Users\Leisure\AppData\Roaming\Typora\typora-user-images\1569479016314.png)]

    • context:include-filter子节点表示要包含的目标类(要结合**use-default-filters=“false”**一起使用)
    • context:exclude-filter子节点表示要排除在外的目标类
    • context:component-scan可以拥有若干个 context:include-filter 和 context:exclude-filter 子节点

2.4 自动装配注解:

context:component-scan元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有**@Autowired @Resource** 、@Inject注解的属性。三个注解用法相似。

@Autowired

  1. 自动装配具有兼容类型的单个Bean属性

  2. 构造器, 普通字段(即使是非 public)一切具有参数的方法都可以应用@Authwired 注解

  3. 默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false

    	@Autowired(required=false)
    	private UserService userService;
    
  4. 默认情况下, 当 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);
    	}
    
  5. @Authwired 注解也可以应用在数组类型、集合、java.util.Map 的属性上。

2.5 泛型依赖注入

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

3、使用Spring的ContextApplication

Spring自带了多种类型的应用上下文。

1 ⭐AnnotationConfigApplicationContext 从一个或多个基于Java的配置类中加载Spirng应用上下文
2 AnnotationConfigWebApplicationContext 从一个或多个基于Java的配置类中加载Spring Web应用上下文。
3 ⭐ClassPathXmlApplicationContext 从类路径下的一个或多个XMl配置文件中加载上下文定义,把应用上下文的定义文件作为资源
4 ⭐FileSystemXmlApplicationContext 从文件系统下的一个或多个XML配置文件中加载上下文定义
5 XmlWebApplicationContext 从Web应用下的一个或多个XMl配置文件中加载上下文定义

3.1 从Java配置中加载上下文(.class文件)

//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);
    }
}

3.2 从类路径加载上下文(xml文件)

//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);

}

3.3 从文件系统加载上下文(xml文件)

//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);

}

⭐ 3.4 从BeanFactory加载(xml文件)

//从类路径下读取配置文件
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.

3.5 使用@Autowired进行自动装配

	@Autowired
	User user;

使用**@Autowired** 时需要使用**@Component**来对应

@Component
public class User {

	private Long id;

	private String name;

	private Integer age;
}

你可能感兴趣的:(Spring相关)