目录
1.Spring配置/管理bean介绍
2.基于XML配置bean
2.1基于id来获取bean对象
2.2基于类型获取bean对象
2.3通过指定构造器配置bean对象
2.4通过p名称空间配置bean
2.5通过ref配置bean(实现依赖注入)
2.6注入内部Bean对象,依赖注入另一种方式
2.7 注入集合/数组类型
使用util名称空间创建list
级联属性赋值配置
2.8 通过静态工厂获取对象
2.9通过实例工厂配置bean
2.10 通过FactoryBean获取bean对象(重点)
2.11 bean配置信息重用(继承)
2.12 Bean创建的顺序
2.13 Bean对象的单例和多例
2.14Bean的生命周期
2.15 配置Bean的后置处理器[重点!难点!]
2.16 通过属性文件给Bean注入值
2.17 基于XML的Bean的自动装配
2.18 Spring的EL表达式配置Bean[基础演示]
2.19 基于注解配置Bean【重点】
2.19.1快速入门案例
2.19.2 细节分析
1.Spring配置/管理bean介绍
Spring-IOC的配置所需要的jar包有四个。
如果你用maven配置则需要导入以下代码在pom.xml文件中
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入ioc的beans基本包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--引入ioc的core基本包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--引入ioc的context基本包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--引入ioc的expression的基本包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--引入一些日志文件-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!--加入单元测试的类-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<!--加入简化开发pojo的jar包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
</dependencies>
</project>
2.基于XML配置bean
注意: xml文件中property属性的配置name的名字必须和你的类的属性名一样,底层是通过类的setter方法进行创建的。
首先会创建一个Monster类
package spring.bean;
/**
* @author sn
*/
public class Monster {
private Integer id;
private String name;
private String skill;
//写一个无参构造函数,spring是用反射来创建对象的
public Monster() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
@Override
public String toString() {
return "Monster{" +
"id=" + id +
", name='" + name + '\'' +
", skill='" + skill + '\'' +
'}';
}
}
2.1基于id来获取bean对象
基于id获取bean的案例,在我的另外一个文章中
2.2基于类型获取bean对象
1. 按类型来获取 bean, 要求 Spring容器中的同一个类的 bean 只能有一个 , 否则会抛出异常NoUniqueBeanDefinitionException2. 应用场景:比如 Controller控制器, 或 XxxService 在一个线程 中只需要一个对象实例 ( 单例 ) 的情况3. 注意 : 在容器配置文件 ( 比如 beans.xml) 中给属性赋值 , 底层是通过 setter 方法完成的 , 这也是为什么我们需要提供 setter 方法的原因这里可以看看我手写底层Spring如何通姑XML创建对象的 链接,去看看
beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过类型来配置bean-->
<bean class="spring.bean.Monster">
<property name="id" value="1"/>
<property name="name" value="小红花"/>
<property name="skill" value="向阳而生"/>
</bean>
</beans>
@Test
public void getTypeBean()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster bean = ioc.getBean(Monster.class);
System.out.println(bean);
}
结果
如果配置了两个bean对象,且用类型来获取该对象(这里bean在xml在配置一个)(X)
如果在Monster中没有setId方法(setter)(X)
我们知道对象在Spring容器的创建是通过反射创建的,属性是通过类对应的setter方法构建的
如果没有setter方法,那么对象在Spring容器中构建不出,就会报错!
2.3通过指定构造器配置bean对象
提示:反射机制创建对象有两种:
1:通过指定的构造器创建对象。
2: 通过对象中的setter和getter方法创建
1:当你用指定构造器创建对象是,就是用这个类中的有参构造创建
2:当你使用id/类型/p命名空间等这些都是用其中的getter和setter方法去创建的对象。(前提是你必须拥有它的无参构造函数!!)
首先要在Monster中写一个全参的构造函数
public Monster(Integer id, String name, String skill) {
this.id = id;
this.name = name;
this.skill = skill;
}
XML文件中通过构造器配置bean对象 (构造器参数的设计三种方式)
1.constructor-arg标签用来指定构造器的参数
2.用index索引表示构造器的第几个参数
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<!--通过指定构造器配置bean -->
<bean class="spring.bean.Monster" id="monster02">
<constructor-arg value="13" index="0"/>
<constructor-arg value="花小龙" index="1"/>
<constructor-arg value="自律遇见更好地自己!" index="2"/>
</bean>
</beans>
1.constructor-arg标签用来指定构造器的参数
2.用name表示构造器的第几个参数
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<!--通过指定构造器配置bean -->
<bean class="spring.bean.Monster" id="monster03">
<constructor-arg value="14" name="id"/>
<constructor-arg value="王老师" name="name"/>
<constructor-arg value="从那天起我再也没羡慕过谁!" name="skill"/>
</bean>
</beans>
1.constructor-arg标签用来指定构造器的参数
2.用type表示构造器的参数(按顺序来)
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<!--通过指定构造器配置bean -->
<bean class="spring.bean.Monster" id="monster04">
<constructor-arg value="520" type="java.lang.Integer"/>
<constructor-arg value="陈泽" type="java.lang.String"/>
<constructor-arg value="在一起!" type="java.lang.String"/>
</bean>
</beans>
测试代码
@Test
public void getConstructorBean()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster bean1 = ioc.getBean("monster02", Monster.class);
Monster bean2 = ioc.getBean("monster03", Monster.class);
Monster bean3 = ioc.getBean("monster04", Monster.class);
System.out.println(bean1);
System.out.println(bean2);
System.out.println(bean3);
}
结果:
2.4通过p名称空间配置bean
p命名空间绑定,直接alt+enter绑定命名空间 (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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过p命名空间来获取-->
<bean class="spring.bean.Monster" id="monster05"
p:id = "1"
p:name="小哥"
p:skill="冒昧呀!"
/>
</beans>
测试代码
@Test
public void getPNameBean()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster bean = ioc.getBean("monster05", Monster.class);
System.out.println(bean);
}
2.5通过ref配置bean(实现依赖注入)
package spring.dao;
/**
* @author sn
*/
public class MemberDao {
public MemberDao() {
System.out.println("MemberDao构造函数被执行");
}
public void add()
{
System.out.println("MemberDao成功添加了一个人");
}
}
配置MemberService类
package spring.service;
import spring.dao.MemberDao;
/**
* @author sn
*/
public class MemberService {
private MemberDao memberDao;
public MemberDao getMemberDao() {
return memberDao;
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public void add()
{
System.out.println("MemberService里面的add方法被调用");
memberDao.add();
}
}
配置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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过ref实现依赖注入-->
<!--首先配置两个独立的对象,要实现对象之间的组装,依赖注入,用到ref
指向id为dao的对象(某个对象的属性是要依赖另外一个对象的) -->
<bean class="spring.dao.MemberDao" id="dao"/>
<bean class="spring.service.MemberService" id="memberService">
<property name="memberDao" ref="dao"/>
</bean>
</beans>
测试类
@Test
public void setBeanByref()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
MemberService bean = ioc.getBean("memberService", MemberService.class);
bean.add();
}
结果
具体说明解释
@1 xml文件的扫描是通过全局扫描的,所以在ref配置对象的id的时候,如另外一个对象在后面,也不会报错,比如在beandefinitonMap里面就有所有的对象的id。
@2 依赖注入,就是一个对象要用到另外一个对象时,spring容器可以去实现。
@3 底层剖析,ref是如何依赖注入对象,或者说是如何精确找到要用的对象的
在spring容器创建过后,可以看到在singletonObject(单例数组对象中) MemberDao是3344,你可以把它理解成hash值。
在这里我们看到了MemberService他的哈希值是3346,他引用的对象MemberDao的值是3343。底层就是通过这种编号来找的。
2.6注入内部Bean对象,依赖注入另一种方式
需求和上一个一样
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过内部bean实现依赖注入-->
<bean class="spring.dao.MemberDao" id="dao"/>
<bean class="spring.service.MemberService" id="memberService">
<property name="memberDao">
<bean class="spring.service.MemberService" />
</property>
</bean>
</beans>
结果也是一样的
2.7 注入集合/数组类型
案例:通过xml中的配置,实现spring容器对集合map list set array properties的注入
定义一个Master类
package spring.bean;
import java.util.*;
/**
* @author sn
*/
public class Master {
private String name;
private List<Monster> monsterList;
private Map<String, Monster> monsterMap;
private Set<Monster> monsterSet;
private String[] monsterName;
//这个 Properties 是 Hashtable 的子类 , 是 key-value 的形式
//这里 Properties key 和 value 都是 String
private Properties pros;
public Master() {
}
public Master(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Monster> getMonsterList() {
return monsterList;
}
public void setMonsterList(List<Monster> monsterList) {
this.monsterList = monsterList;
}
public Map<String, Monster> getMonsterMap() {
return monsterMap;
}
public void setMonsterMap(Map<String, Monster> monsterMap) {
this.monsterMap = monsterMap;
}
public Set<Monster> getMonsterSet() {
return monsterSet;
}
public void setMonsterSet(Set<Monster> monsterSet) {
this.monsterSet = monsterSet;
}
public String[] getMonsterName() {
return monsterName;
}
public void setMonsterName(String[] monsterName) {
this.monsterName = monsterName;
}
public Properties getPros() {
return pros;
}
public void setPros(Properties pros) {
this.pros = pros;
}
@Override
public String toString() {
return "Master{" +
"name='" + name + '\'' +
", monsterList=" + monsterList +
", monsterMap=" + monsterMap +
", monsterSet=" + monsterSet +
", monsterName=" + Arrays.toString(monsterName) +
", pros=" + pros +
'}';
}
}
beans.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置Master对象-->
<bean class="spring.bean.Master" id="master">
<property name="name" value="主人1"/>
<property name="monsterList">
<list>
<!--通过引入的方式-->
<ref bean="monster01"/>
<ref bean="monster02"/>
<bean class="spring.bean.Monster">
<property name="name" value="小老鼠"/>
<property name="id" value="2"/>
<property name="skill" value="会钻洞"/>
</bean>
</list>
</property>
</bean>
<!--对map属性进行一个赋值-->
<bean class="spring.bean.Master" id="master2">
<property name="name" value="主人2"/>
<property name="monsterMap">
<map>
<entry>
<key>
<value>monster01</value>
</key>
<ref bean="monster01"/>
</entry>
<entry key="monster002">
<bean class="spring.bean.Monster">
<property name="name" value="小红"/>
<property name="id" value="1"/>
<property name="skill" value="摘樱桃"/>
</bean>
</entry>
</map>
</property>
</bean>
<!--对set属性进行一个赋值-->
<bean class="spring.bean.Master" id="master3">
<property name="name" value="主人三"/>
<property name="monsterSet">
<set>
<ref bean="monster02"/>
<ref bean="monster03"/>
<bean class="spring.bean.Monster">
<property name="id" value="15"/>
<property name="name" value="金角大王"/>
<property name="skill" value="会洗澡"/>
</bean>
</set>
</property>
</bean>
<!--对数组进行赋值-->
<bean class="spring.bean.Master" id="master4">
<property name="name" value="主人4"/>
<property name="monsterName">
<array>
<value>小球1</value>
<value>小球2</value>
<value>小球3</value>
</array>
</property>
</bean>
<!--对properties进行赋值-->
<bean class="spring.bean.Master" id="master5">
<property name="pros">
<props>
<prop key="username">张三</prop>
<prop key="password">12354</prop>
</props>
</property>
</bean>
<!--通过指定构造器配置bean -->
<bean class="spring.bean.Monster" id="monster02">
<constructor-arg value="13" index="0"/>
<constructor-arg value="花小龙" index="1"/>
<constructor-arg value="自律遇见更好地自己!" index="2"/>
</bean>
<bean class="spring.bean.Monster" id="monster03">
<constructor-arg value="14" name="id"/>
<constructor-arg value="王老师" name="name"/>
<constructor-arg value="从那天起我再也没羡慕过谁!" name="skill"/>
</bean>
<bean class="spring.bean.Monster" id="monster04">
<constructor-arg value="520" type="java.lang.Integer"/>
<constructor-arg value="陈泽" type="java.lang.String"/>
<constructor-arg value="在一起!" type="java.lang.String"/>
</bean>
<!--通过p命名空间来获取-->
<bean class="spring.bean.Monster" id="monster05"
p:id = "1"
p:name="小哥"
p:skill="冒昧呀!"
/>
<!--通过ref实现依赖注入-->
<!--首先配置两个独立的对象,要实现对象之间的组装,依赖注入,用到ref
指向id为dao的对象(某个对象的属性是要依赖另外一个对象的) -->
<bean class="spring.dao.MemberDao" id="dao"/>
<bean class="spring.service.MemberService" id="memberService">
<property name="memberDao" ref="dao"/>
</bean>
<!--通过类型来配置bean
<bean class="spring.bean.Monster">
<property name="id" value="1"/>
<property name="name" value="小红花"/>
<property name="skill" value="向阳而生"/>
</bean>-->
<!--
1.配置Monster对象/javabean
2.在beans中可以配置多个bean
3.class属性指定的是类的全路径
4.id属性表示java对象在spring容器中的id,通过id可以获取对象
5.<property name="skill" value="向阳而生"/>是用来给该对象赋值
-->
<bean class="spring.bean.Monster" id="monster01">
<property name="id" value="1"/>
<property name="name" value="小红花"/>
<property name="skill" value="向阳而生"/>
</bean>
</beans>
测试文件
@Test
public void setBeanByList()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master bean = ioc.getBean("master", Master.class);
System.out.println("master=>"+bean);
}
@Test
public void setBeanByMap()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master bean = ioc.getBean("master2", Master.class);
System.out.println("master=>"+bean);
}
@Test
public void setBeanBySet()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master bean = ioc.getBean("master3", Master.class);
System.out.println("master=>"+bean);
}
@Test
public void setBeanByArray()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master bean = ioc.getBean("master4", Master.class);
System.out.println("master=>"+bean);
}
@Test
public void setBeanByProperties()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Master bean = ioc.getBean("master5", Master.class);
System.out.println("master=>"+bean);
}
使用util名称空间创建list
他的作用:就是当多个对象进行复用该list集合的时候,就可以直接引用,看代码。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!--定义一个util:list命名空间 -->
<util:list id="books">
<value>三国演义</value>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
</util:list>
<!--配置BookStore对象-->
<bean class="spring.bean.BookStore" id="bookStore">
<property name="bookList" ref="books"/>
</bean>
</beans>
不需要和之前List的注入时,要将所有List写出来,当如果多个对象都有这个List,就可以进行一个代码的复用 。
级联属性赋值配置
spring 的 ioc 容器 , 可以直接给对象属性的属性赋值, 即级联属性赋值
需求是:员工类有名字和部门类,创建对象的时候给他的名字,以及属性的属性部门的名字赋值
Dept部门类
package spring.bean;
/**
* @author sn
*/
public class Dept {
private String name;
public Dept() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
Emp员工类
package spring.bean;
/**
* @author sn
*/
public class Emp {
private String name;
public Emp() {}
private Dept dept;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", dept=" + dept +
'}';
}
}
测试类
@Test
public void setBeanByJILian()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Emp emp = ioc.getBean("emp", Emp.class);
System.out.println("emp=>"+emp);
}
beans.xml
<!--级联属性赋值-->
<bean class="spring.bean.Dept" id="dept"/>
<bean class="spring.bean.Emp" id="emp">
<property name="name" value="张三"/>
<property name="dept" ref="dept"/>
<property name="dept.name" value="语言开发部门"/>
</bean>
结果
2.8 通过静态工厂获取对象
在 spring 的 ioc 容器 , 可以通过静态工厂获取 bean 对象
具体解释:
使用静态工厂,就算创建了两个静态工厂,但是他们仍然是同一个工厂。就相当于静态类,有且只有一个
静态工厂类
package spring.bean;
import java.util.HashMap;
import java.util.Map;
/**
* @author sn
*/
public class MyStaticFactory {
private static Map<String, Monster> monsterMap;
static {
monsterMap = new HashMap<String, Monster>();
monsterMap.put("monster_01", new Monster(100, "黄袍怪", "一阳指"));
monsterMap.put("monster_02", new Monster(200, "九头金雕", "如来神掌"));
}
public static Monster getMonster(String key) {
return monsterMap.get(key);
}
}
beans.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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!--通过静态工厂获取bean对象
factory-method:是从静态工厂中要使用的方法
constructor-arg:你要从工厂里面取出对象的id
-->
<bean id="my_monster" class="spring.bean.MyStaticFactory"
factory-method="getMonster">
<!-- constructor-arg 标签提供 key -->
<constructor-arg value="monster_01"/>
</bean>
</beans>
2.9通过实例工厂配置bean
在 spring 的 ioc 容器, 可以通过实例工厂获取 bean 对象
实例工厂和静态工厂的异同:
相同:他们都是从自创的工厂中直接获取对象,不需要在xml中对对象重新进行信息的配置
不同:
类比于Java的静态类和普通类
1. 在写法上,静态工厂,不需要一个真正的工厂对象,就可以调用里面的方法。而实例工厂,必须要用一个实例工厂对象才行。
2. 静态工厂有且只有一个,每个从静态工厂中拿出id一样的对象都是相同的。
实例工厂可以有多个,当你创建多个实例工厂对象,从不同工厂拿出id一样的对象是不同的。
假如你配置了两个实例工厂对象,那么这两个工厂就是不同的工厂,里面的对象也只是属性值都相同的不同的对象。
实例工厂
package spring.bean;
import java.util.HashMap;
import java.util.Map;
/**
* @author sn
*/
public class MyInstanceFactory {
private Map<String, Monster> monster_map;
//通过普通代码块进行初始化
{
monster_map = new HashMap<>();
monster_map.put("monster03", new Monster(300, "牛魔王~", "芭蕉扇~"));
monster_map.put("monster04", new Monster(400, "狐狸精~", "美人计~"));
}
//写一个方法返回Monster对象
public Monster getMonster(String key) {
return monster_map.get(key);
}
}
XML文件
<!--通过实例工厂配置bean对象-->
<!--配置monster对象, 通过实例工厂
1. factory-bean 指定使用哪个实例工厂对象返回bean
2. factory-method 指定使用实例工厂对象的哪个方法返回bean
3. constructor-arg value="monster03" 指定获取到实例工厂中的哪个monster -->
<bean class="spring.bean.MyInstanceFactory" id="myInstanceFactory"/>
<bean factory-bean="myInstanceFactory" factory-method="getMonster" id="monster">
<constructor-arg value="monster03"/>
</bean>
2.10 通过FactoryBean获取bean对象(重点)
在 spring 的 ioc 容器 , 通过 FactoryBean 获取 bean 对象 ( 重点 )
FactoryBean实现这个接口
MyFactoryBean
package spring.bean;
import org.springframework.beans.factory.FactoryBean;
import java.util.HashMap;
import java.util.Map;
/**
* @author sn
*/
public class MyFactoryBean implements FactoryBean<Monster> {
//key就是要获取的对像的key
private String key;
private Map<String,Monster> monster_map;
//用普通代码块,完成初始化
{
monster_map = new HashMap<>();
monster_map.put("monster_01", new Monster(100, "黄袍怪", "一阳指"));
monster_map.put("monster_02", new Monster(200, "九头金雕", "如来神掌"));
}
public void setKey(String key) {
this.key = key;
}
@Override
public Monster getObject() throws Exception {
return monster_map.get(key);
}
@Override
public Class<?> getObjectType() {
return Monster.class;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
XML
1. 通过 FactoryBean 来获取 bean 对象2. name="keyVal" 就是 MyFactoryBean 定义的 setKeyVal 方法3. value="monster_01" ,就是给 keyVal 的值
<!--配置monster对象通过FactorBean获取-->
<bean class="spring.bean.MyFactoryBean" id="myFactoryBean">
<property name="key" value="monster_01"/>
</bean>
2.11 bean配置信息重用(继承)
在 spring 的 ioc 容器, 提供了一种继承的方式来实现 bean 配置信息的重用
1. 如果bean指定了 abstract="true", 表示该bean对象, 是专门用于被继承 。
2. 本身这个bean就不能被获取/实例化,也就是说你在Spring容器中获取不了该对象。3. parent="monster10" 指定当前这个配置的对象的属性值从 id=monster10的对象来。
<!--配置Monster对象-->
<bean class="spring.bean.Monster" id="monster10">
<property name="name" value="陆雪琪"/>
<property name="id" value="1"/>
<property name="skill" value="爱上张小凡"/>
</bean>
<!--
1. 配置Monster对象
2.但是这个对象的属性值和 id="monster10"对象属性一样
3.parent="monster10" 指定当前这个配置的对象的属性值从 id=monster10的对象来 -->
<bean id="monster11" class="spring.bean.Monster" parent="monster10"/>
<!--配置Monster对象
1. 如果bean指定了 abstract="true", 表示该bean对象, 是用于被继承
2. 本身这个bean就不能被获取/实例化 -->
<bean class="spring.bean.Monster" id="monster13" abstract="true">
<property name="name" value="陆雪琪"/>
<property name="id" value="1"/>
<property name="skill" value="爱上张小凡"/>
</bean>
2.12 Bean创建的顺序
<bean id="student01" class="com.bean.Student" /><bean id="department01" class="com.bean.Department" />会先创建 student01 这个 bean 对象,然后创建 department01 这个 bean 对象
<bean id="student01" class="com.bean.Student" depends-on ="department01"/><bean id="department01" class="com.bean.Department" />会先创建 department01 对象,再创建 student01 对象
3.注意重点
Bean对象的创建一直都是按顺序进行创建。 Spring容器创建是对整个XML文件进行扫描,以一个整体进行创建的
2.13 Bean对象的单例和多例
1. 在 spring 的 ioc 容器 , 在 默认是按照单例创建的 ,即配置一个 bean 对象后, ioc 容器只会 创建一个 bean 实例。2. 如果 , 我们希望 ioc 容器配置的某个 bean 对象, 是以多个实例形式创建的则可以通过配置scope="prototype" 来指定3. 如果bean的配置是 scope="singleton" lazy-init="true" 这时,ioc容器就不会提前创建该对象 , 而是当执行getBean方法的时候,才会创建对象
xml
<!--配置对象
1. 在默认情况下 scope属性是 singleton
2. 在ioc容器中, 只要有一个这个bean对象
3. 当程序员执行getBean时, 返回的的是同一个对象
4. 如果我们希望每次getBean返回一个新的Bean对象,则可以scope="prototype"
5. 如果bean的配置是 scope="singleton" lazy-init="true" 这时,
ioc容器就不会提前创建该对象 , 而是当执行getBean方法的时候,才会创建对象 -->
<bean class="spring.bean.Monster" id="monster2" scope="prototype"
p:id="3"
p:name="小王"
p:skill="会生孩"
/>
测试代码
@Test
public void testBeanByScope()
{
//先获取容器
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster bean = ioc.getBean("monster2", Monster.class);
Monster bean2 = ioc.getBean("monster2", Monster.class);
System.out.println("bean = bean2:"+ (bean == bean2));
}
最后的结果是false,因为指定了scope=prototype
使用细节
1. 默认是单例 singleton, 在启动容器时 , 默认会创建 , 并放入到 singletonObjects 集合2. 当 <bean scope="prototype" > 设置为多实例机制后 , 该 bean 是在 getBean() 时才创建3. 如 果 是 单 例 singleton, 同 时 希 望 在 getBean 时 才 创 建 , 可 以 指 定 懒 加 载lazy-init ="true" ( 注意默认是 false)4. 通常情况下 , lazy-init 就使用默认值 false , 在开发看来 , 用空间换时间是值得的 , 除非有特殊的要求 .5. 如果 scope="prototype" 这时你的 lazy-init 属性的值不管是 ture, 还是 false 都是在getBean 时候,才创建对象 .
2.14Bean的生命周期
Bean对象是由JVM虚拟机创建的,他具体创建bean对象的执行流程如下:
1. 执行构造器2. 执行 set 相关方法3. 调用 bean 的初始化的方法(需要配置)4. 使用 bean5. 当容器关闭时候,调用 bean 的销毁方法(需要配置)
1. init-method="init" 指定bean的初始化方法 , 在setter方法后执行
2. init方法执行的时机,有spring容器来控制
3. destroy-method="destroy" 指定bean的销毁方法, 在容器关闭的时候执行
4. destroy方法执行的时机,有spring容器来控制
创建一个House类
package spring.bean;
/**
* @author sn
*/
public class House {
private String name;
public House() {
System.out.println("House()构造函数被调用");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("House setName()="+name);
this.name = name;
}
public void init()
{
System.out.println("House init()..");
}
public void destroy() {
System.out.println("House destory()..");
}
}
<!-- 配置House对象,演示Bean的生命周期
1. init-method="init" 指定bean的初始化方法 , 在setter方法后执行
2. init方法执行的时机,有spring容器来控制
3. destroy-method="destroy" 指定bean的销毁方法, 在容器关闭的时候执行
4. destroy方法执行的时机,有spring容器来控制
-->
<bean class="spring.bean.House" id="house"
init-method="init" destroy-method="destroy">
<property name="name" value="小马"/>
</bean>
@Test
public void testBeanByLive()
{
//先获取容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
House house = ioc.getBean("house", House.class);
System.out.println("使用"+house);
//关闭spring容器
((ConfigurableApplicationContext) ioc).close();
}
注意这里为什么要转换类型,再调用其close方法呢:因为ApplicatonContext没有这个方法,那么他的字接口有。
2.15 配置Bean的后置处理器[重点!难点!]
1. 在 spring 的 ioc 容器 , 可以配置 bean 的后置处理器2. 该处理器 / 对象会在 bean 初始化方法 调用前和初始化方法调用后被调用3. 程序员可以在后置处理器中编写自己的代码4. 可以将该处理器可以看做一个对象5. 只要在xml文件中创建了该后置处理器对象,他会作用于所有的xml中配置的对象6. 怎么执行到这个方法?=> 使用 AOP(反射+动态代理+IO+容器+注解)7. 有什么用? => 可以 对 IOC 容器中所有的对象进行统一处理 , 比如 日志处理 / 权限的校验 / 安全的验证 / 事务管理8. 创建后置处理器对象,要实现BeanPostProcesser接口
后置处理器对象创建
package spring.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author sn
* * 这是一个后置处理器, 需要实现 BeanPostProcessor接口
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 什么时候被调用: 在Bean的init方法前被调用
* @param bean 传入的在IOC容器中创建/配置Bean
* @param beanName 传入的在IOC容器中创建/配置Bean的id
* @return Object 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization().. bean="
+ bean + " beanName=" + beanName);
//初步体验案例: 如果类型是House的统一改成 上海豪宅
//对多个对象进行处理/编程==>切面编程
/* if(bean instanceof House) {
((House)bean).setName("上海豪宅~");
}*/
return null;
}
/**
* 什么时候被调用: 在Bean的init方法后被调用
* @param bean 传入的在IOC容器中创建/配置Bean
* @param beanName 传入的在IOC容器中创建/配置Bean的id
* @return 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization().. bean="
+ bean + " beanName=" + beanName);
return bean;
}
}
beans02.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置House对象-->
<bean destroy-method="destroy" init-method="init" id="house" class="spring.bean.House">
<property value="住宅" name="name"/>
</bean>
<bean destroy-method="destroy" init-method="init" id="house02" class="spring.bean.House">
<property value="豪宅" name="name"/>
</bean>
<!--配置了一个Monster对象-->
<!--配置后置处理器对象
1. 当我们在beans02.xml 容器配置文件 配置了 MyBeanPostProcessor
2. 这时后置处理器对象,就会作用在该容器创建的Bean对象
3. 已经是针对所有对象编程->切面编程AOP -->
<bean id="myBeanPostProcessor" class="spring.bean.MyBeanPostProcessor"/>
</beans>
测试类
@Test
public void testBeanByPostProcesser()
{
//先获取容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans02.xml");
House house = ioc.getBean("house", House.class);
House house2 = ioc.getBean("house02", House.class);
System.out.println("使用"+house);
System.out.println("使用"+house2);
//关闭spring容器
((ConfigurableApplicationContext) ioc).close();
}
结果分析
2.16 通过属性文件给Bean注入值
一切都在代码中的注释中进行解释,请耐心看完。
如何处理配置文件中中文的问题:
在配置文件中通过工具,将中文转换为Unicode编码就可以了
Unicode编码转换 | Unicode在线转换 —在线工具
beans01.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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--指定属性文件
1. 先把这个文件修改成提示All Problem
2. 提示错误,将光标放在context 输入alt+enter 就会自动引入namespace
3. location="classpath:my.properties" 表示指定属性文件的位置
4. 提示,需要带上 classpath
5. 属性文件有中文,需要将其转为unicode编码-> 使用工具 -->
<context:property-placeholder location="classpath:my.properties"/>
<!--配置Monster对象
1.通过属性文件给monster对象的属性赋值
2. 这时我们的属性值通过${属性名}
3. 这里说的 属性名 就是 my.properties文件中的 k=v 的k -->
<bean id="monster100" class="spring.bean.Monster">
<property value="${id}" name="id"/>
<property value="${skill}" name="skill"/>
<property value="${name}" name="name"/>
</bean>
</beans>
配置文件
id=100
name=jd
skill=hello,boy
2.17 基于XML的Bean的自动装配
在 spring 的 ioc 容器,可以实现自动装配 bean
首先配置三个类OrderAvtion-->OrderService-->OrderDao
OrderAction
package spring.controller;
import spring.service.OrderService;
/**
* @author sn
* Servlet就是Controller
*/
public class OrderAction {
//属性OrderService
private OrderService orderService;
//getter
public OrderService getOrderService() {
return orderService;
}
//setter
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
}
OrderService
package spring.service;
import spring.dao.OrderDao;
/**
* @author sn
* Service类
*/
public class OrderService {
//OrderDao属性
private OrderDao orderDao;
//getter
public OrderDao getOrderDao() {
return orderDao;
}
//setter
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
OrderDao
package spring.dao;
/**
* @author sn
* DAO类 只有一个saveOrder()方法
*/
public class OrderDao {
//方法。。。
public void saveOrder() {
System.out.println("订单...");
}
}
<!--配置OrderService
1. autowire="byType" 表示 在创建 orderService时通过类型的方式 给对象属性 自动完成赋值/引用
2. 比如OrderService 对象有 private OrderDao orderDao
3. 就会在容器中去找有没有 OrderDao类型对象
4. 如果有,就会自动的装配, 如果是按照 byType 方式来装配, 这个容器中,不能有两个的OrderDao类型对象
5. 如果你的对象没有属性, autowire就没有必要写
6. 其它类推..
7. 如果我们设置的是 autowire="byName" 表示通过名字完成自动装配
8. 比如下面的 autowire="byName" class="spring.service.OrderService"
1) 先看 OrderService 属性 private OrderDao orderDao
2) 再根据这个属性的setXxx()方法的 xxx 来找对象id
3) public void setOrderDao() 就会找id=orderDao对象来进行自动装配
4) 如果没有就装配失败 -->
<!--配置orderDao对象-->
<bean class="spring.dao.OrderDao" id="orderDao"/>
<!--配置orderService对象-->
<bean autowire="byType" class="spring.service.OrderService" id="orderService"/>
<!--配置orderAction-->
<bean autowire="byName" class="spring.controller.OrderAction" id="orderAction"/>
具体解释
@1 在对象中有一个属性为autowire,里面几种自动装配的方法,这里具体介绍了byName和byType
@2 如果使用byType,对于OrderAction中有一个对象属性为orderService的对象,他会去扫描整个Spring容器,找到一个类型是OrderService的对象进行一个自动的装配,没有找到责装配失败。
@3 注意的是如果通过byType的形式,在Spring容器中只能有一种这种类型的对象
@4 如果采用byName的形式,他会去寻找OrderAction中的对于对象属性的Setter方法所对应的id,而不是去找对象属性的变量名的id比如,在上诉代码中寻找setOrderService()方法中的,id为orderService的对象进行装配
2.18 Spring的EL表达式配置Bean[基础演示]
1. Spring Expression Language , Spring 表达式语言,简称 SpEL 。支持运行时查询并可以操 作对象。2. 和 EL 表达式一样, SpEL 根据 JavaBean 风格的 getXxx() 、 setXxx() 方法定义的属性访问 对象3. SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL 表达式。
配置SpELBean类
package spring.bean;
/**
* @author sn
*/
public class SpELBean {
private String name;
private Monster monster;
private String monsterName;
private String crySound;
private String bookName;
private Double result;
public SpELBean() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Monster getMonster() {
return monster;
}
public void setMonster(Monster monster) {
this.monster = monster;
}
public String getMonsterName() {
return monsterName;
}
public void setMonsterName(String monsterName) {
this.monsterName = monsterName;
}
public String getCrySound() {
return crySound;
}
public void setCrySound(String crySound) {
this.crySound = crySound;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public Double getResult() {
return result;
}
public void setResult(Double result) {
this.result = result;
}
public String cry(String sound) {
return "发出 " + sound + "叫声...";
}
public static String read(String bookName) {
return "正在看 " + bookName;
}
}
我觉得这个EL表达式挺方便的
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<!-- spring el 表达式使用
1. 通过spel给bean的属性赋值 -->
<bean class="spring.bean.SpELBean" id="spELBean">
<!-- sp el 给字面量 -->
<property value="#{'效率'}" name="name"/>
<!-- sp el 引用其它bean -->
<property value="#{monster01}" name="monster"/>
<!-- sp el 引用其它bean的属性值 -->
<property value="#{monster01.name}" name="monsterName"/>
<!-- sp el 调用普通方法(返回值) 赋值 -->
<property value="#{spELBean.cry('嘟嘟的..')}" name="crySound"/>
<!-- sp el 调用静态方法(返回值) 赋值 -->
<property value="#{T(spring.bean.SpELBean).read('书籍')}" name="bookName"/>
<!-- sp el 通过运算赋值 -->
<property value="#{1.2}" name="result"/>
</bean>
</beans>
2.19 基于注解配置Bean【重点】
如果不知道注解是啥可以看一下链接:Java注解(三种JDK内置基本注解、四种元注解的介绍,源码分析!)-CSDN博客
基于注解的方式配置 bean, 主要是项目开发中的组件,比如 Controller 、 Service 、和 Dao.● 组件注解的形式有1. @Component 表示当前注解标识的是一个组件【 是一个通用的标识 】2. @Controller 表示当前注解标识的是一个控制器,通常用于 Servlet3. @Service 表示当前注解标识的是一个处理业务逻辑的类,通常用于 Service 类4. @Repository 表示当前注解标识的是一个持久化层的类,通常用于 Dao 类
用注解的形式必须使用一个包,将其进行引入在你下载的spring-framework包下
2.19.1快速入门案例
实例:使用注解的方式来配置 Controller / Service / Respository / Component
首先配置四个类(带有其注解的)
MyComponent
package spring.component;
import org.springframework.stereotype.Component;
/**
* @author sn
* @Component 标识该类是一个组件, 是一个通用的注解
*/
@Component
public class MyComponent {
}
UserAction
package spring.component;
import org.springframework.stereotype.Controller;
/**
* @author sn
* @version 1.0
* @Controller 标识该类是一个控制器Controller, 通常这个类是一个Servlet
*/
@Controller
public class UserAction {
}
UserService
package spring.component;
import org.springframework.stereotype.Service;
/**
* @author sn
* @version 1.0
* @Service 标识该类是一个Service类/对象
*/
@Service
public class UserService {
//方法..
public void hi(){
System.out.println("UserService hi()~");
}
}
UserDao
package spring.component;
import org.springframework.stereotype.Repository;
/**
* @author sn
* @version 1.0
* 使用 @Repository 标识该类是一个Repository是一个持久化层的类/对象
* 1. 标记注解后,类名首字母小写作为id的值(默认)
* 2. value = "hspUserDao" 使用指定的 hspUserDao作为UserDao对象的id
*/
@Repository
public class UserDao {
}
测试类
@Test
public void setBeanByAnnotation()
{
//先获取容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans05.xml");
//通过类型去获取
UserAction userAction = ioc.getBean(UserAction.class);
UserDao userDao = ioc.getBean(UserDao.class);
UserService userService = ioc.getBean(UserService.class);
//通过id名进行获取
MyComponent myComponent = ioc.getBean("myComponent", MyComponent.class);
System.out.println(myComponent+"\n" + userAction + "\n" +
userService + "\n" + userDao);
}
beans.xml
配置容器要扫描的包
1. component-scan 要对指定包下的类进行扫描, 并创建对象到容器
2. base-package 指定要扫描的包
3. 含义是当spring容器创建/初始化时,就会扫描spring.component包下的所有的 有注解 @Controller / @Service / @Respository / @Component类将其实例化,生成对象,放入到ioc容器。
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--配置容器要扫描的包-->
<!--
配置容器要扫描的包
1. component-scan 要对指定包下的类进行扫描, 并创建对象到容器
2. base-package 指定要扫描的包
3. 含义是当spring容器创建/初始化时,就会扫描spring.component包下的所有的 有注解 @Controller / @Service / @Respository / @Component类将其实例化,生成对象,放入到ioc容器
-->
<context:component-scan base-package="spring.component"/>
</beans>
debug展示
2.19.2 细节分析
@1. 需要导入 spring-aop-5.3.8.jar , 别忘了
@2. 必须在 Spring 配置文件中指定 " 自动扫描的包 " , IOC 容器才能够检测到当前项目中哪些类被标识了注解, 注意到导入 context 名称空间<!-- 配置自动扫描的包 --><context:component-scan base-package="spring.component" />可以使用通配符 * 来指定 ,比如 spring.* 表示-- 提问 : spring.component 会不会去扫描它的子包 ?答:会的3. Spring 的 IOC 容器不能检测一个使用了 @Controller 注解的类到底是不是一个真正的控制器。注解的名称是用于程序员自己识别当前标识的是什么组件。其它的 @Service@Repository 也是一样的道理 [ 也就是说 spring 的 IOC 容器只要检查到注解就会生成对象, 但是这个注解的含义 spring 不会识别,注解是给程序员编程方便看的 ], 也就是说spring容器会根据注解创建对象,他自己确不知道注解的含义4.<context:component-scan base-package="spring.component"resource-pattern="User*.class" />resource-pattern="User*.class": 表示只扫描User开头的类。扫描.class是因为在运行时实际扫描的是out目录下的文件,这些文件被编译成了字节码文件[ 使用的少 ,不想扫描,不写注解就可以 , 知道这个知识点即可 ]
@5 对于要排除的类,可以按形式进行:需求:如果我们希望排除某个包/子包下的某种类型的注解,可以通过exclude-filter来指定
1. context:exclude-filter 指定要排除哪些类
2. type 指定排除方式 annotation表示按照注解来排除
3. expression="org.springframework.stereotype.Service" 指定要排除的注解的全路径
<!--需求:如果我们希望排除某个包/子包下的某种类型的注解,可以通过exclude-filter来指定
1. context:exclude-filter 指定要排除哪些类
2. type 指定排除方式 annotation表示按照注解来排除
3. expression="org.springframework.stereotype.Service" 指定要排除的注解的全路径 -->
<context:component-scan base-package="spring.component">
<context:exclude-filter expression="org.springframework.stereotype.Service" type="annotation"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter expression="org.springframework.stereotype.Repository" type="annotation"/>
</context:component-scan>
@6 可以指定要自动扫描那些类 YU @5相反
1. use-default-filters="false": 不再使用默认的过滤机制2. context:include-filter: 表示只是扫描指定的注解的类3. expression="org.springframework.stereotype.Controller": 注解的全类名
<context:component-scan base-package="spring.component" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
@ 7. 默认情况:标记注解后,类名首字母小写作为 id 的值。也可以使用注解的 value 属性
指定 id 值,并且 value 可以省略。@Controller(value="userAction2")@Controller("userAction2")