Loading

Spring 5(二):IOC容器

概述

IOC(Inversion of Control):控制反转,把对象的创建和对象之间调用的过程交给Spring进行管理

使用IOC的目的:降低耦合度

IOC是一种设计思想,DI(依赖注入)是实现IOC的一种方法

IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

在没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方

实质:获得依赖对象的方式反转了

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(DI)

底层原理

IOC的底层原理涉及三个技术点:

  • xml解析
  • 工厂模式
  • 反射

引入

假设现在有:

  • 一个 Service类
  • 一个 Dao接口
  • 一个 Dao实现类
interface UserDao {
    void add();
}

class UserDaoImpl implements UserDao {
    @Override
    public void add() {
    }
}

class UserService {
	public void execute() {
    }
}

Service类 中,如果我们想要调用 Dao类 中的方法,我们需要实例化 Dao类

class UserService {
    
    private UserDao userDao = new UserDaoImpl();
    
	public void execute() {
        userDao.add();
    }
}

需求:增加一个新的实现类,客户如何使用

解答:需要到Service中改变userDao变量的类型,这样做每新增加一个类,都需要修改原有的代码

缺点:耦合度太高

这种做法可以达到我们的需求,但如果dao类修改代码,整个程序的代码都需要修改,耦合度太高,为此,,我们需要降低耦合度(高内聚,低耦合)

改进:利用set进行动态实现值的注入

class UserService {
    
    private UserDao userDao;
    
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    
	public void execute() {
        userDao.add();
    }
}

测试:

public class TestDemo {
    public static void main(String[] args) {
        UserService service = new UserService();
        service.setUserDao(new UserDaoImpl());
        service.execute();
    }
}

分析

在没有使用set之前,程序主动创建对象,控制权在程序员手上

当利用set注入后,程序不再具有主动性,而是变成了被动的接收对象

例如:新增需求Mysql的实现

只需要扩展一个新类,不需要修改原来代码,用户修改一下用户类就可以调用这个新类

public class TestDemo {
    public static void main(String[] args) {
        UserService service = new UserService();
        service.setUserDao(new UserDaoMysqlImpl());
        service.execute();
    }
}

工厂模式

为了降低程序的耦合度,我们使用工厂模式来解耦

操作:创建一个工厂类,让工厂来创建对象

public class UserFactory {
    public static UserDao getDao() {
        return new UserDao();
    }
}

现在,如果想要在Service中调用Dao的方法,不需要new一个Dao对象,只需要调用工厂类的getDao方法即可

public class UserService {
	private void execute() {
        UserDao dao = UserFactory.getDao();
        dao.add();
    }
}

而我们的最终目的:耦合度降低到最低限制!

IOC解耦

为了进一步降低耦合度,我们使用IOC进行解耦

具体步骤:

  1. 在maven中导入Spring相关jar包
  2. 创建实体类
  3. 创建并配置核心配置文件 applicationContext.xml
  4. 在Service类中调用Dao方法
  • maven配置
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.5</version>
    </dependency>
</dependencies>
<bean id="dao" class="com.yue.UserDao"></bean>

接口

通过加载配置文件的方式,Spring提供IOC容器实现两种方式:

  • BeanFactory:IOC容器基本实现,是Spring内部使用的接口,一般不提供给开发人员使用
  • ApplicationContext:是BeanFactory的子接口,提供了更多、更强大的功能
    • 实现类:
    • FileSystemXmlApplicationContext:使用全盘符路径
    • ClassPathXmlApplicationContext:使用类路径

区别:

  • BeanFactory接口在加载配置文件的时候不会创建对象,在获取对象(使用)才去创建对象
  • ApplicationContext接口在加载配置文件的时候就会创建配置文件内的对象

Spring配置

别名alias

给bean起别名使用标签 alias

<alias name="user" alias="别名" />

bean标签

bean标签里面的属性有

  • id:bean的唯一标识,相当于对象名
  • class:bean对象所对应的全限定名(包名+类型)
  • name:别名,可以取多个别名,用逗号/分号隔开,也可以用空格分隔;跟id的作用一样,不同的是name中可以加特殊符号,如_

import

导入其他配置文件

<import resource="" />

Bean管理

Bean管理实际指的是两个操作:

  1. 创建对象
  2. 依赖注入

Bean管理操作有两种方式:

  1. 基于 **xml配置文件 **方式实现
  2. 基于 注解 方式实现

创建对象(xml)

做法:在xml配置文件中,使用bean标签创建对象,标签里面添加对应的属性

<bean id="dao" class="com.yue.UserDao"></bean>

在创建对象的时候,默认执行无参数构造方法

依赖注入(xml)

依赖注入(DI)就是注入属性,DI是IOC的一种具体实现

  • 依赖:bean对象的创建依赖于容器
  • 注入:bean对象中的所有属性,由容器来注入

例如:现在实体类User现在有一个属性 : name

public class User {
    private String name;
}

实现:在创建对象的过程中,向User的属性name设置一个值

实现方式:

  • set注入
  • 有参构造方式
  • 扩展方式

set注入

set注入方式:在实体类中创建对应的set方法

public class book {

    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

在Spring的配置文件中,使用 property标签 对bean属性进行配置

<bean id="book" class="com.yue.pojo.Book">
    <!--
            使用property完成属性注入
            name:类里面属性的名称
            value:向属性注入的值
        -->
    <property name="name" value="易筋经" />
    <property name="author" value="达摩" />
</bean>

p名称空间

对于set方法注入的xml文档编写,可以使用p名称空间进行代码的简化

具体使用步骤:

  1. 现在配置文件中加入p名称空间
xmlns:p="http://www.springframework.org/schema/p"
  1. 在使用set注入的时候,简写方式为:
<bean id="book" class="com.yue.pojo.Book" p:name="九阳神功" p:author="无名氏"></bean>

构造器注入

实现:在实体类中创建带参数的构造方法

class book {

    private String name;

    public Book(String name) {
        this.name = name;
    }
}

在Spring的配置文件中,使用 constructor-arg标签 对bean属性进行配置

<bean id="orders" class="com.yue.pojo.Orders">
    <constructor-arg name="name" value="电脑" />
    <constructor-arg name="address" value="China" />
</bean>

或者:通过索引值来赋值

 <constructor-arg index="0" value="" />

还可以通过参数类型来创建

c命名空间

与p命名空间类似,但必须要有构造器注入

字面量注入

字面量包括:

  • null值
  • 属性值包含特殊符号

null值的设置

null值得注入使用 null标签

<bean id="book" class="com.yue.pojo.Book">
    <property name="name"> 
        <null />
    </property>
</bean>

特殊符号

如果想要给属性值设置特殊符号如:<<>>,实现方法有:

  • 需要使用转义字符
  • 把带特殊符号内容写到CDATA表达式中,CDATA表达式会把内容原样输出
<property name="address">
    <value>
        <![CDATA[
               <<南京>>
        ]]>
    </value>
</property>

bean注入

bean注入得方式:

  • 外部bean注入
  • 内部bean注入

外部bean

service为一个bean,该bean中有一个dao对象属性,在对service进行bean创建时,需要引入bean之外的bean

  • 创建外部bean:dao的实现类
<bean id="userDaoImpl" class="com.yue.dao.UserDaoImpl" />
  • 创建本bean,并引入外部bean,使用ref属性引入
<bean id="userService" class="com.yue.service.UserService">
    <!--
		在service中注入dao
		ref属性:创建userDaoImpl对象bean标签的id值
	-->
    <property name="userDao" ref="userDaoImpl"></property>
</bean>
  • 测试
@Test
public void TestAdd() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
}

内部bean

对于引入外部bean的方式,还可以在bean中定义bean

<bean id="userService" class="com.yue.service.UserService">
    <property name="userDao">
        <bean id="userDaoImpl" class="com.yue.dao.UserDaoImpl"></bean>
    </property>
</bean>

级联赋值

级联赋值有两种写法

第一种:与外部bean类似

<bean id="emp" class="com.yue.pojo.Emp">
    <property name="name" value="蓝天" />
    <property name="gender" value="男" />
    <!--设置对象类型属性-->
    <property name="dept" ref="dept" />
</bean>

<bean id="dept" class="com.yue.pojo.Dept">
    <property name="name" value="巡天" />
</bean>

第二种:这种写法需要在emp中生成dept的 get方法

<bean id="emp" class="com.yue.pojo.Emp">
    <property name="name" value="蓝天" />
    <property name="gender" value="男" />
    <!--设置对象类型属性-->
    <property name="dept" ref="dept" />
    <property name="dept.name" value="巡查"/>
</bean>
<bean id="dept" class="com.yue.pojo.Dept" />

集合注入

  • 注入数组类型
  • 注入List集合
  • 注入Map集合
  • 注入Set集合
  • 注入对象集合

现在有一个实体类Student,包含五种集合

public class Course {
    private String name;
}
public class Student {
    private String[] courses;
    private List<String> list;
    private Map<String, String> maps;
    private Set<String> sets;
    private List<Course> courseList;

    public void test() {
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
    }
}
  • 在配置文件中配置
<!--集合类型注入-->
<bean id="student" class="com.yue.pojo.Student" >
    <!--数组类型注入-->
    <property name="courses">
        <array>
            <value>语文</value>
            <value>数学</value>
            <value>英语</value>
        </array>
    </property>	

    <!--list类型注入-->
    <property name="list">
        <list>
            <value>张三</value>
            <value>李四</value>
        </list>
    </property>

    <!--Map类型注入-->
    <property name="maps">
        <map>
            <entry key="JAVA" value="java"></entry>
            <entry key="PHP" value="php"></entry>
        </map>
    </property>

    <!--Set集合注入-->
    <property name="sets">
        <set>
            <value>MySQL</value>
            <value>Redis</value>
        </set>
    </property>


    <!--集合对象注入方式-->
    <!--注入list集合类型,值是对象-->
    <property name="courseList">
        <list>
            <ref bean="course1"/>
            <ref bean="course2"/>
        </list>
    </property>

</bean>

<!--创建多个course对象-->
<bean id="course1" class="com.yue.pojo.Course">
    <property name="name" value="Spring5框架" />
</bean>

<bean id="course2" class="com.yue.pojo.Course">
    <property name="name" value="Mybatis框架" />
</bean>
  • 测试
@Test
public void StudentTest() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Student student = context.getBean("student", Student.class);
    student.test();
}

提取集合注入部分

使用 util 标签进行注入提取

  • 先创建一个Book类
public class Book {
    private List<String> list;

    public void test() {
        System.out.println(list);
    }
}
  • 在配置文件中引入名称util
<?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 http://www.springframework.org/schema/util/spring-util.xsd">
</beans>
  • 使用util标签完成list集合注入提取
<!--提取list集合-->
<util:list id="bookList">
    <value>易筋经</value>
    <value>九阳神功</value>
    <value>九阴真经</value>
</util:list>

<!--注入使用-->
<bean id="book" class="com.yue.pojo.Book">
    <property name="list" ref="bookList"/>
</bean>
  • 测试
@Test
public void BookTest() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Book book = context.getBean("book", Book.class);
    book.test();
}

Properties注入

使用props标签对properties文件的注入

<bean id="book" class="com.yue.pojo.Book">
    <property name="info">
        <props>
            <prop key="">值</prop>
            <prop key="">值</prop>
            <prop key="">值</prop>
        </props>
    </property>
</bean>

FactoryBean

Spring有两种类型bean,一种普通bean,另外一种叫工厂bean(FactoryBean)

  • 普通bean:在配置文件中,定义的bean类型就是返回类型
  • 工厂bean:在配置文件中,定义的bean类型可以和返回的类型不一样

  1. 创建一个类,让这个类作为工厂bean,实现接口FactoryBean
  2. 实现接口里面的方法,在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Course> {

    //定义返回bean
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setName("abc");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
<bean id="myBean" class="com.yue.pojo.MyBean"></bean>
@Test
public void MyBeanTest() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Course myBean = context.getBean("myBean", Course.class);
    System.out.println(myBean);
}

bean的作用域

在Spring里面,可以设置创建的bean实例是单实例还是多实例

默认情况下,bean是单实例对象

使用 scope标签 设置作用域

scope属性值:

  • singleton:默认值
  • prototype:多实例对象
  • request
  • session
  • application
  • websocket
<bean id="myBean" class="com.yue.pojo.MyBean" scope="prototype" />

测试:

@Test
public void MyBeanTest() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    MyBean myBean = context.getBean("myBean", MyBean.class);
    MyBean myBean2 = context.getBean("myBean", MyBean.class);
    System.out.println(myBean);
    System.out.println(myBean2);
}

输出的两个bean对象是不一样的

singleton与prototype的区别

  • singleton单实例,prototype多实例
  • singleton:加载spring配置文件的时候就会创建单实例对象
  • prototype:不是在加载spring配置文件的时候创建对象,而是在调用getBean方法的时候创建多实例对象

bean的生命周期

生命周期:从对象的创建到对象销毁的过程

bean生命周期:

  • 通过构造器创建bean实例(无参数构造)
  • 为bean的属性设置值和对其他bean的引用(调用set方法)
  • 调用bean的初始化的方法(需要进行配置)
  • bean的使用
  • 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)
public class Orders {

    private String name;

    public Orders() {
        System.out.println("第一步、执行无参构造创建bean实例");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步、调用set方法设置属性值");
    }

    //创建执行的初始化的方法
    public void initMethod() {
        System.out.println("第三步、执行初始化方法");
    }

    //创建执行的销毁方法
    public void destroyMethod() {
        System.out.println("第五步、执行销毁方法");
    }
}
<bean id="orders" class="com.yue.pojo.Orders" init-method="initMethod" destroy-method="destroyMethod"/>
@Test
public void OrdersTest() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Orders orders = context.getBean("orders", Orders.class);
    System.out.println("第四步、获取创建bean实例对象");
    System.out.println(orders);

    //手动让bean实例销毁
    ((ClassPathXmlApplicationContext)context).close();
}

后置处理器

bean的生命周期一共有七步:

  1. 通过构造器创建bean实例(无参数构造)
  2. 为bean的属性设置值和对其他bean的引用(调用set方法)
  3. 把bean的实例传递给bean后置处理器的方法 postProcessBeforeInitialization
  4. 调用bean的初始化的方法(需要进行配置)
  5. 把bean的实例传递给bean后置处理器的方法 postProcessAfterInitialization
  6. bean的使用
  7. 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)

需要先添加后置处理器,创建一个类,实现接口BeanPostProcessor,实现两个方法

MyBeanPost

public class MyBeanPost implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return bean;
    }

}

并且需要在配置文件中配置一下

<bean id="myBeanPost" class="com.yue.pojo.MyBeanPost" />

自动装配

在Spring中有三种装配的方式:

  • 在xml中显示的配置
  • 在Java中显示配置
  • 隐式的自动装配bean

手动装配:在创建对象时使用property标签进行依赖注入

自动装配:根据指定配置规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

假设有员工和部门类

class Dept {

}
class Emp {
    private String name;
    private Dept dept;
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public void setName(String name) {
        this.name = name;
    }
}

bean配置

<bean id="emp" class="com.yue.pojo.Emp" >
    <property name="name" value="yue" />
    <property name="dept" ref="dept"/>
</bean>

<bean id="dept" class="com.yue.pojo.Dept" />

使用 autowire 完成自动装配

autowire的属性值:

  • byName:根据属性名注入,注入值bean的id值和类属性名称要一样

    会自动在容器上下文中查找,和自己对象set方法后面对应的beanid

    例如,在emp类中有个Dept属性,并且有setDept方法,会自动在配置文件中找id为dept的bean自动装配

<bean id="emp" class="com.yue.pojo.Emp" autowire="byName" />
<bean id="dept" class="com.yue.pojo.Dept" />
  • byType:根据属性类型注入

    会自动在容器上下文中查找,和自己对象属性类型相同的bean

    弊端:必须保证类型全局唯一

<bean id="emp" class="com.yue.pojo.Emp" autowire="byType" />
<bean id="dept" class="com.yue.pojo.Dept" />

properties文件引入

把一些固定的、相关的值放到一个其他文件中,然后把文件引入xml文件中

例如:操作数据库时,数据库有一些固定值,把这些固定值放到一个文件中,然后在xml中读取文件中的配置

原始方式:直接在xml中配置数据库信息

  1. 先引入连接池druid的jar包到maven中
  2. 在xml配置文件中配置
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/userDb" />
    <property name="username" value="root" />
    <property name="password" value="1234" />
</bean>

引入外部属性文件

  1. 先创建一个外部属性文件,properties格式文件,写入数据库信息
driverClassName= com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ems?useUnicode=true&characterEncoding=UTF-8&&serverTimezone=GMT
username=root
password=1234
initialSize=5
maxActive=10
maxWait=3000
timeBetweenEvictionRunsMillis=60000
validationQuery=SELECT 1
maxPoolPreparedStatementPerConnectionSize=200
  1. 把外部properties文件引入到spring配置文件中
  • 引入context名称空间
<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"
       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/util http://www.springframework.org/schema/util/spring-util.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  • 在spring配置文件中使用标签引入外部属性文件
<context:property-placeholder location="druid.properties" />

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
    <property name="driverClassName" value="${driverClassName}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
</bean>

注解

使用注解需要先配置注解的支持,必须保证aop包的导入

<?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:根据 属性类型 进行自动装配
  • @Qualifier:根据 属性名称 进行注入
  • @Resource:可以根据类型注入,也可以根据名称注入
  • @Value:注入普通类型属性

使用注解 @Autowired ,默认byType方式

class Emp {
    private String name;

    @Autowired
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public void setName(String name) {
        this.name = name;
    }
}
<bean id="emp" class="com.yue.pojo.Emp" />
<bean id="dept" class="com.yue.pojo.Dept" />

通过添加这个注解,set方法也可以去掉

class Emp {
    private String name;

    @Autowired
    private Dept dept;

    public void setName(String name) {
        this.name = name;
    }
}

使用注解 @Nullable 说明这个字段可以为null,如

public Emp(@Nullable String name) {
    this.name = name;
}

@Autowired有一个默认值:@Autowired(required = true)

如果显示的定义为false,说明这个对象可以为null,否则不允许为空


如果有多个相同的对象,@Autowired识别不了哪个,可以使用注解 @Qualifier 配合使用,例如

class Emp {
    private String name;

    @Autowired
    @Qualifier(value = "dept2")
    private Dept dept;

    public void setName(String name) {
        this.name = name;
    }
}
<bean id="dept" class="com.yue.pojo.Dept" />
<bean id="dept2" class="com.yue.pojo.Dept" />

还可以使用注解 @Resource 进行自动装配

该注解会先找名字,如果名字找不到,会找类型,如果有多个类型一致的,会返回错误

可以给该注解添加属性进行精确查找

class Emp {
    private String name;

    @Resource(name = "dept2")
    private Dept dept;

    public void setName(String name) {
        this.name = name;
    }
}

使用 @Value 注解可以注入普通类型

public class UserService {
    @Value("abc")
    private String name;
}

@Autowired与@Resource的区别:

  • 都是用来自动装配的,都可以放在属性字段上
  • @Autowired是通过byType方式实现,而且必须要求这个对象存在
  • @Resource默认通过byName方式实现,如果找不到名字,则通过byType实现,如果两个都找不到,就报错
  • 执行顺序不同

创建对象

使用 @Component 注解来创建bean

@Component
public class Emp {
}

这个bean的默认id为类名的小写

@Component:组件,放在类上,说明这个类被Spring管理了,就是bean


@Component有几个衍生注解,在web开发中,会按照mvc三层架构分层:

  • dao:@Repository
  • service:@Service
  • controller:@Controller

这四个注解,功能一样,都可以创建bean的实例,都是代表将某个类注册到Spring中,装配bean

@Repository
public class UserDao {
}

@Service
public class UserService {
}

@Controller
public class UserController {
}

作用域

作用域的注解为:@Scope

@Scope("singleton")  //单例模式
@Scope("prototype")  //多例
public class User {
}

组件扫描

除了使用下面开启注解的支持外,还可以使用 component-scan 扫描某些包下面的注解

<context:annotation-config/>

注解扫描:

<context:component-scan base-package="com.yue" />

组件扫描的是整个包下面的类,如何避开某些类不扫描呢?

示例:

<context:component-scan base-package="com.yue" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • use-default-filters="false":表示现在不使用默认filter,使用自己配置的filter
  • context:include-filter:设置扫描哪些内容

这里设置扫描带注解Controller的类

context:exclude-filter:设置哪些内容不进行扫描

<context:component-scan base-package="com.yue" use-default-filters="false">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

完全注解开发

使用注解 @Configuration 完成完全注解开发

自定义一个配置类,例如 SpringConfig,并在类的上面添加注解@Configuration,使之成为一个配置类,替代xml配置文件

@Configuration
@ComponentScan(basePackages = "com.yue")
public class SpringConfig {

    //注册一个bean
    //方法名字就相当于bean标签的id,返回值就相当于class
    @Bean
    public User getUser() {
        return new User();
    }
}

实体类

@Component
public class User {
    @Value("lan")
    private String name;
}

编写测试类

@Test
public void Test() {
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    User getUser = context.getBean("getUser", user.class);
    System.out.println(getUser.getName());
}
posted @ 2021-04-19 16:49  qinuna  阅读(82)  评论(0编辑  收藏  举报