Spring笔记

目录

1、Spring IOC控制反转

2、Spring

3、Spring IoC体验

3.1.在pox.xml加入Spring的依赖

3.2.配置applicationContext.xml

3.3、使用ApplicationContext获取IoC容器

4、初始化IOC容器

5、基于XML配置bean

6、实例化bean的三种方法

6.1利用构造方法参数实例化

6.2利用静态工厂实例化对象

6.3基于工厂实例方法实例化

7.从IOC容器获取bean

8、classpath:路径表达式

9、属性的依赖注入

9.1基于setter方法注入对象

9.2利用构造方法实现对象的依赖注入

10、注入集合对象

10.1注入List

11、查看容器内的对象

12、bean的scope属性

13、bean的生命周期

14、实现极简IOC容器

15、基于注解配置IOC容器

16、 基于注解创建IOC容器

17、两类自动装配注解

 18、元数据注解

19、基于java Config

20、java Config

21、Spring Test测试模块


1、Spring IOC控制反转

1.IOC控制反转,全称Inverse of Control,是一种设计理念

2.由代理人来创建与管理对象,消费者通过代理人来获取对象

3.Ioc的目的是为了降低对象之间的耦合性

4.通过加入Ioc容器将对象统一管理,让对象关联变为弱耦合

IOC控制反转:将目标对象创建的权力从最开始的消费者,转给中间的角色在容器(IOC控制反转容器)中集中管理,消费者不再对对象直接操作,由IoC容器从中进行提取,获取其中的对象。

DI(Dependency Injection)依赖注入:java通过反射技术来实现,让运行时的程序动态执行,DI在不用语言中的实现是不一样的

2、Spring

"Spring Make Java Sample"

Spring狭义上是指Spring框架(Spring Fremework),广义上指的是Spring生态体系

Microservices分布式微服务:使用可独立发展的微服务快速交付生产级功能--SpringClould

Reactive:Spring的异步、非阻塞架构意味着可以从计算资源中获得更多收益

Cloud:任何代码,任何云,无论平台如何,都可以连接和拓展服务

Web apps:用于连接到任何数据存储的快速、安全和响应式Web应用程序的框架

Serverless:无服务器编程,摆脱服务器,极致的灵活性,按需拓展并在没有需求时拓展至零

Event Driven:事件驱动,与企业集成,对业务事件做出反应,实时处理流数据

Batch:自动化任务,批处理

为什么要用Spring?

传统开发方式(Controller--Service--Dao),对象直接应用导致对象硬性关联,程序难以拓展维护,当某一层改变代码时,需要重新进行修改、测试、上线等,流程很不方便。

利用Spring在运行时基于JAVA的反射完成对象的创建和关联------DI。

 

使用者提取对象A,在IOC容器中将A对象的依赖B注入到A();

反射让程序运行时,将指定的对象和其他对象进行关联。

3、Spring IoC体验

3.1.在pox.xml加入Spring的依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
</dependencies>

3.2.配置applicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    每个对象都放在<bean></bean>中,由IOC容器统一管理,并且为每个Bean贴上标签id-->
<!--    当对象改变时,只需要更改property中的内容,无需更改主函数中的源代码-->
<!--在Ioc容器启动时,自动由Spring实例化Apple对象,取名为sweetApple放入容器中-->
    <bean id="sweetApple" class="com.test.spring.ioc.entity.Apple">
        <property name="title" value="红富士"></property>
        <property name="origin" value="欧洲"></property>
        <property name="color" value="红色"></property>
    </bean>
<!--    将程序中写死的部分,写活,每写一个Bean,在IOC容器启动时,会在容器中创建对应的对象-->
    <bean id="sourApple" class="com.test.spring.ioc.entity.Apple">
        <property name="title" value="青苹果"></property>
        <property name="origin" value="中亚"></property>
        <property name="color" value="绿色"></property>
    </bean>

    <bean id="softApple" class="com.test.spring.ioc.entity.Apple">
        <property name="title" value="金帅"></property>
        <property name="origin" value="中国"></property>
        <property name="color" value="黄色"></property>
    </bean>
</beans>

3.3、使用ApplicationContext获取IoC容器

public class SpringApplication {
    public static void main(String[] args) {
        //context对象就对应了Ioc容器,赋值classpath:applicationContext.xml,向Ioc容器中加入对象
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        //通过getBean的方式获取对象,传入的参数为<bean的id,对象.class>
        Apple sweetApple = context.getBean("sweetApple", Apple.class);//"sweetApple"代表bean的id
        System.out.println(sweetApple.getTitle());//红富士
        //所谓IOC容器,就是通过配置文件applicationContext.xml,在不通过new对象的前提下,来获取对象
    }
}

4、初始化IOC容器

共有三种配置IOC容器的方法

  1. 基于XML applicationContext.xml配置bean
  2. 基于注解配置bean
  3. 基于java代码 javaConfig配置bean

5、基于XML配置bean

使用XML创建IOC容器,bean的属性包括id(为对象类的名字)、class(为类的路径)

<property name="" value=""></property> ---为类中的属性进行赋值

//创建IOC容器并根据配置文件的<bean></bean>创建对象
ApplicationContext context = new ClassPathApplicationContext("classpath:applicationContext.xml");
<!--    bean默认用无参构造方法来创建对象-->
<bean class="com.test.Spring.IoC.entity.Apple" id="apple1"/>

6、实例化bean的三种方法

  1. 基于构造方法对象实例化
  2. 基于静态工厂实例化
  3. 基于工厂实例方法实例化

6.1利用构造方法参数实例化

可以通过<constructor-arg name=" " value=" ">实例化

设置为三个参数的构造方法,IOc容器被创建时,会去Apple类中寻找符合title、origin、color三个参数的构造方法

<!--通过带参构造方法实例化对象,利用反射技术赋值-->
<bean class="com.test.Spring.IoC.entity.Apple" id="apple2">
        <constructor-arg name="title" value="红富士"/>
        <constructor-arg name="color" value="红色"/>
        <constructor-arg name="origin" value="欧洲"/>
</bean>

还可以通过类中构造方法的参数的位置对应进行赋值

<!--通过带参构造方法实例化对象,利用反射技术赋值-->
<bean class="com.test.Spring.IoC.entity.Apple" id="apple2">
        <constructor-arg index="0" value="红富士"/>
        <constructor-arg index="1" value="红色"/>
        <constructor-arg index="2" value="欧洲"/>
</bean>

6.2利用静态工厂实例化对象

创建Factory类AppleStaticFactory,在类中创建对象并赋值,返回类对象

然后再applicationContext.xml中声明factory-method = “类的名字” 

package com.test.Spring.IoC.Factory;

import com.test.Spring.IoC.entity.Apple;

public class AppleStaticFactory {
    //此处方法为静态的属于AppleStaticFactory类
    public static Apple createSweetApple(){
        Apple apple = new Apple();
        apple.setTitle("红富士");
        apple.setOrigin("欧洲");
        apple.setColor("红色");
        return apple;
    }
}
<!--静态工厂的目的,在ioc容器之外创建对象,隐藏创建对象时的具体逻辑,可以在工厂代码中加入其他逻辑-->
<bean id="apple3" class="com.test.Spring.IoC.Factory.AppleStaticFactory" factory-method="createSweetApple"/>

6.3基于工厂实例方法实例化

创建工厂类AppleFactoryInstance

package com.test.Spring.IoC.Factory;

import com.test.Spring.IoC.entity.Apple;
/**
 * 工厂实例方法创建对象是指Ioc容器对工厂类进行实例化并调用对应的实例方法对象的过程
 */
public class AppleFactoryInstance {
    //此处方法为非静态方法,不属于类,属于类的对象
    public Apple createSweetApple(){
        Apple apple = new Apple();
        apple.setTitle("红富士");
        apple.setOrigin("欧洲");
        apple.setColor("红色");
        return apple;
    }
}
<!--利用工厂实例化方法创建对象,对象方法不用static时,需要先实例化工厂类-->
<!--实例化工厂类获取factory-bean,再实例化工厂类的方法-->
<bean id="factoryInstance" class="com.test.Spring.IoC.Factory.AppleFactoryInstance"/>
<bean id="apple5" factory-bean="factoryInstance" factory-method="createSweetApple"/>

实例化bean共有三种方法,主要使用第一种利用构造方法实例化bean

7.从IOC容器获取bean

要获取bean的类对象,可以使用context.getBean()方法,参数传入bean ID

Apple sweetApple = context.getBean("sweetApple",Apple.class);
Apple sweetApple = (Apple)context.getBean("sweetApple");
System.out.println(sweetApple.getTitle);

 

 优先使用id对bean经行标识

8、classpath:路径表达式

classpath:applicationContext.xml--加载当前路径下的--xml文件

指的是编译过后的target目录下的xml文件

 加载target-classes-com-applicationContext.xml

 

 9、属性的依赖注入

对象依赖注入有两种方法:

  • 基于setter方法注入对象
  • 基于构造方法注入对象

9.1基于setter方法注入对象

setter方法的注入分为静态数值的注入和对象的注入

 apple通过IOC容器依赖注入到child

<!--使用setter方法为对象赋值,静态数值-->
<bean id="sweetApple" class="com.test.spring.IoC.entity.Apple">
        <property name="title" value="红富士"/>
        <property name="color" value="红色"/>
        <property name="origin" value="欧洲"/>
<!--Spring IoC会将"19.8"自动转化成需要的类型-->
        <property name="price" value="19.8"/>
</bean>

 ref : 对象注入,将sweetApple与name:莉莉 关联起来

<!--创建IoC容器ApplicationContext时,
先通过setter静态创建sweetApple对象,随后通过setter将sweetApple注入到child中-->
<bean class="com.test.spring.IoC.entity.Child" id="lili">
        <property name="name" value="lili"/>
<!--利用ref实现对象的注入,ref为注入对象对象的ID-->
        <property name="apple" ref="sweetApple"/>
</bean>

通过上面bean的对象注入,当创建IoC容器时,会先创建Apple对象,在创建Child对象,在DI Apple对象到Child对象的apple属性中

依赖注入的优势

applicationContext-dao.xml
<!--这里的的class不能为接口对象,必须为接口的实现类BookDaoImpl-->
<bean id="bookDao" class="com.test.spring.ioc.bookshop.dao.BookDaoImpl(1/2)"/>
applicationContext-sercice.xml
<!--BookService在运行时需要用到BookDao,
BookService不需要管用到的BookDao的实现类是哪个,
只需要ref创建的Dao就可以了
-->
<bean class="com.test.spring.ioc.bookshop.service.BookService" id="bookService">
    //传入ref为:"bookDao" 当接口的逻辑改变时,只需要修改bookDao的class实体类就行
    <property name="bookDao" ref="bookDao"/>
</bean>
//Dao
public interface BookDao {
    public void insert();
}

public class BookDaoImpl implements BookDao{
    public void insert(){
        System.out.println("向mysql插入一条数据");
    }
}
//当接口逻辑改变时即 BookDaoImpl-->BookDaoImpl2 ,需要修改applicationContext-dao.xml
public class BookDaoImpl2 implements BookDao{
    public void insert() {
        System.out.println("向redis数据库表插入一条数据");
    }
}
//BookService
package com.test.spring.ioc.bookshop.service;

import com.test.spring.ioc.bookshop.dao.BookDao;

public class BookService {
    //此处只需要传入接口就行,方便后期需要修改时的代码的维护
    private BookDao bookDao;

    public void purchase(){
        System.out.println("执行采购图书的业务");
        bookDao.insert();
    }
//getter and setter
}
public class BookShopApplication {
    public static void main(String[] args) {
        //按照xml.的先后顺序实例化Ioc容器
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-*.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        bookService.purchase();
    }
}

9.2利用构造方法实现对象的依赖注入

依赖注入是指运行时将容器内对象利用反射赋给其他对象的操作

先初始化Apple对象sourApple,再将Child对象中的属性name、apple通过基于构造方法注入

	<bean id="sourApple" class="com.test.spring.IoC.entity.Apple">
        <property name="title" value="青苹果"/>
        <property name="color" value="绿色"/>
        <property name="origin" value="中亚"/>
        <!--Spring IoC会将"19.8"自动转化成需要的类型-->
        <property name="price" value="9.8"/>
    </bean>

    <bean id="andy" class="com.test.spring.IoC.entity.Child">
        <constructor-arg name="name" value="andy"/>
    <!--当构造方法中存在对象时,可以使用ref传入对象,
    通过IoC容器利用反射将sourApple注入到child对象中-->
        <constructor-arg name="apple" ref="sourApple"/>
    </bean>

public static void main(String[] args) {
        ApplicationContext context = new 			ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        Child child = context.getBean("andy", Child.class);
        child.eat();
    }

10、注入集合对象

在bean中注入的集合对象分为四类

  1. List
  2. Set
  3. Map
  4. Properties

10.1注入List

 

 

 

 Properties 传入的key Value 只能使用字符串

package com.test.spring.ioc.entity;

import java.util.List;
import java.util.Map;
import java.util.Properties;

public class company {
    private List<String> rooms;
    private Map<String,computer> computers;
    private Properties info;
}
package com.test.spring.ioc.entity;

public class computer {
    private String brand;
    private String type;
    private String sn;
    private Float price;
}
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.test.spring.ioc.entity.computer" id="c1">
        <constructor-arg name="brand" value="lianxiang"/>
        <constructor-arg name="type" value="taishiji"/>
        <constructor-arg name="sn" value="8389283012"/>
        <constructor-arg name="price" value="3085"/>
    </bean>

    <bean id="company" class="com.test.spring.ioc.entity.company">
        <property name="rooms">
            <list>
                <value>2001-总裁办</value>
                <value>2003-总经理办公室</value>
                <value>2010-研发部办公室</value>
            </list>
<!--            <set>-->
<!--                <value>2001-总裁办</value>-->
<!--                <value>2003-总经理办公室</value>-->
<!--                <value>2010-研发部办公室</value>-->
<!--                <value>2010-研发部办公室</value>-->
<!--            </set>-->
        </property>

        <property name="computers">
            <map>
                <entry key="dev-88172" value-ref="c1"/>
                <entry key="dev0-88173">
                    <bean class="com.test.spring.ioc.entity.computer">
                        <constructor-arg name="brand" value="lianxiang"/>
                        <constructor-arg name="type" value="taishiji"/>
                        <constructor-arg name="sn" value="3333"/>
                        <constructor-arg name="price" value="3333"/>
                    </bean>
                </entry>
            </map>
        </property>

        <property name="info">
            <props>
                <prop key="phone">12345678</prop>
                <prop key="address">广州市番禺区</prop>
                <prop key="webSite">www.gdut.edu.cn</prop>
            </props>
        </property>
    </bean>
</beans>

11、查看容器内的对象

要查看IOC容器内的bean对象,需要使用context.getBeanDefinitionNames()方法,返回的是String[]类型的数组

        //获取容器内所有的beanNames数组
        String[] beanNames = context.getBeanDefinitionNames();
        for(String beanName : beanNames){
            System.out.println(beanName);
            System.out.println("类型:" + context.getBean(beanName).getClass().getName());
            System.out.println("内容:" + context.getBean(beanName));
        }
        // 如果一个bean没有Id属性,则会显示class的完整路径匿名bean
        //如果内部写的bean则不会被获取。

c1:
类型:com.test.spring.ioc.entity.computer
内容:computer{brand='lianxiang', type='taishiji', sn='8389283012', price=3085.0}
company:
类型:com.test.spring.ioc.entity.company
内容:company{rooms=[2001-总裁办, 2003-总经理办公室, 2010-研发部办公室], computers={dev-88172=computer{brand='lianxiang', type='taishiji', sn='8389283012', price=3085.0}, dev0-88173=computer{brand='lianxiang', type='taishiji', sn='3333', price=3333.0}}, info={webSite=www.gdut.edu.cn, phone=12345678, address=广州市番禺区}}

12、bean的scope属性

bean scope属性用于决定对象何时被创建与作用范围

bean scope配置将影响容器内对象的数量

bean scope默认值singleton(单例),指全局共享同一个对象实例,默认情况下bean会在IoC容器创建后自动实例化,全局唯一

 

 实例化bean的时间点:singleton为创建IoC容器时创建,prototype为getBean时创建

<bean id="userDao" class="com.test.spring.ioc.Dao.UserDao" scope="prototype"/>

<bean class="com.test.spring.ioc.service.UserService" id="userService">
    <property name="userDao"  ref="userDao"/>
</bean>
//scope默认为单例模式
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }
}
//由于getBean(),则多例模式的bean不会被初始化,优先按顺序初始化scope为singleton的bean
//先初始化UserService的默认构造方法,再调用set方法时先去实例化一个UserDao对象,再set
//UserService已经创建com.test.spring.ioc.service.UserService@13c78c0b
//UserDao已创建com.test.spring.ioc.Dao.UserDao@548a9f61
//调用UserDaocom.test.spring.ioc.Dao.UserDao@548a9f61

13、bean的生命周期

    <bean id="order1" class="com.test.spring.ioc.entity.order" 
          init-method="init" destroy-method="destory">//这里放init-method和destroy-method
        <property name="price" value="19.8"/>
        <property name="numbers" value="1000"/>
    </bean>

package com.test.spring.ioc.entity;

public class order {
    private float price;
    private Integer numbers;
    private float totalPrice;

    public order(){
        System.out.println("创建order方法");
    }

    public void init(){
        System.out.println("执行init方法");//初始化方法1
        totalPrice = price * numbers;
    }

    public void destory(){
        System.out.println("释放与订单对象相关的资源");//销毁容器方法3
    }

    public void pay(){
        System.out.println("订单金额为:"+totalPrice);//业务方法2
    }
}
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");//创建容器
        order o1 = context.getBean("order1", order.class);//赋值于容器,init();
        o1.pay();//业务逻辑方法 pay();
        //销毁容器的方法 destory();
        ((ClassPathXmlApplicationContext)context).registerShutdownHook();
    }
}
声明周期历程:
创建order方法 //执行了构造方法
设置price //bean中为对象注入属性
执行init方法  //IoC容器初始化完成
订单金额为:19800.0 //执行业务逻辑方法
释放与订单对象相关的资源 //销毁IoC容器

14、实现极简IOC容器

IOC容器的实质就是解析XML文件后,将id 、Class存入map中保存,遇到propertity时,利用反射技术将方法名进行获取,最后通过Method.invoke(对象,值)进行setter;

    <dependencies>
<!--        Dom4j是java的XML解析组件-->
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.1</version>
        </dependency>
<!--jaxen是XPATH的解释器-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
    </dependencies>
package com.test.spring.ioc.entity;

public class Apple {
    private String title;
    private String color;
    private String origin;
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean id="sweetApple" class="com.test.spring.ioc.entity.Apple">
        <property name="title" value="红富士"/>
        <property name="color" value="红色"/>
        <property name="origin" value="欧洲"/>
    </bean>
</beans>
package com.test.spring.ioc.context;

public interface ApplicationContext {
    public Object getBean(String beanId);
}
package com.test.spring.ioc.context;
public class ClassPathApplicationContext implements ApplicationContext{
    private Map iocContainer = new HashMap();
    public ClassPathApplicationContext(){
        try{
            //获取到xml的路径
            String filePath = this.getClass().getResource("/applicationContext.xml").getPath();
            filePath = new URLDecoder().decode(filePath,"UTF-8");
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File(filePath));
            List<Node> beans = document.getRootElement().selectNodes("bean");
            for(Node node : beans){
                Element ele = (Element)node;
                String id = ele.attributeValue("id");
                String className = ele.attributeValue("class");
                Class c = Class.forName(className);
                Object obj = c.newInstance();
                List<Node> properties = ele.selectNodes("property");
                for(Node p : properties){
                    Element property = (Element)p;
                    String popName = property.attributeValue("name");
                    String popValue = property.attributeValue("value");

                    String setMethodName = "set"+popName.substring(0,1).toUpperCase()+popName.substring(1);
                    Method setMethod = c.getMethod(setMethodName,String.class);
                    setMethod.invoke(obj,popValue);//通过setter方法注入容器
                }
                iocContainer.put(id,obj);
            }
            System.out.println("IOc容器初始化完毕");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public Object getBean(String beanId) {
        return iocContainer.get(beanId);
    }
}
package com.test.spring.ioc;

import com.test.spring.ioc.context.ApplicationContext;
import com.test.spring.ioc.context.ClassPathApplicationContext;
import com.test.spring.ioc.entity.Apple;

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathApplicationContext();
        Apple apple = (Apple) context.getBean("sweetApple");
        System.out.println(apple);
    }
}

15、基于注解配置IOC容器

前面使用了XML来配置IOc容器

 

 

@Component ---通用注解
@Controller ---控制器类注解Controller
@Service ---服务类注解Service
@Repository ---业务持久层注解Dao

需要现在applicationContext.xml中配置xml

16、 基于注解创建IOC容器

Ioc容器创建时,会先去扫描xml中的base-package="com.test"目录下类是否含有注解,并将其实例化含有四个注解的类,注解创建出来的对象是单例的,其beanId为小写类型或者自己设置的("类名");

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
</dependencies>
<?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">
<!--   在IOC容器初始化时自动扫描四种组件类型注解并完成实例化
        @Repository
        @Service
        @Controller
        @Component
 -->
    <context:component-scan base-package="com.test"/>
</beans>
package com.test.spring.ioc.dao;

import org.springframework.stereotype.Repository;
//组件类型注解默认为beanId为类名首字母小写 beanId = userDao
//该类为数据持久化,IOc会扫描该类
@Repository
public class UserDao {
}
package com.test.spring.ioc.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public static void main(String[] args) {
    }
}
package com.test.spring.ioc.controller;

@org.springframework.stereotype.Controller
public class Controller {
    public static void main(String[] args) {
    }
}
package com.test.spring.ioc.utils;

import org.springframework.stereotype.Component;

@Component
public class StringUtils {
    public static void main(String[] args) {
    }
}
package com.test.spring.ioc;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringApplication {
    public static void main(String[] args) {
        //注解模式是单例的
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");//实例化对象
        String[] ids = context.getBeanDefinitionNames();//获取beanId的名字
        for(String s : ids){
            System.out.println(s+":"+context.getBean(s));
        }
    }
}
//beanIdm默认为小写字母开头的类名
//controller:com.test.spring.ioc.controller.Controller@1d7acb34
//userDao:com.test.spring.ioc.dao.UserDao@48a242ce
//userService:com.test.spring.ioc.service.UserService@1e4a7dd4
//stringUtils:com.test.spring.ioc.utils.StringUtils@4f51b3e0

17、两类自动装配注解

 

 

 18、元数据注解

@Scope()

@Scope("prototype")//设置单例/多例

@PostConstruct

@PostConstruct //XML中bean init-method完全相同
public void init(){
    System.out.println("初始化UserService对象");
}

@Value()

@Value("${metaData}")//为属性赋予静态数值,读取config.properties的key为metaData属性值 
private String metaData;
<context:property-placeholder location="classpath:comfig.properties"/>
<!--通知Spring IOC容器 初始化时 加载属性文件-->
<!--读取comfig.properties的配置文件-->
//应用程序的配置信息properties,创建配置文件
metaData = staticValue

19、基于java Config

除了使用xml或注解配置IOC容器外,还可以使用java Config配置

Spring3.0后才出现

Java Config的优势
1.完全摆脱XML的束缚,使用独立Java类管理对象与依赖
2.注解配置相对分散,利用java Config可以对配置集中管理
3.可以在编译时进行依赖检查,不容易出错

public class UserDao {}

public class UserService {
    private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

public class UserController {
    private UserService userService;

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
package com.test.spring.ioc;
/**
 * java Config使用java类替代XML和注解
 */

@Configuration//当前类是一个配置类,用于替代applicationContext
public class Config {
    @Bean//java config利用方法创建对象,将方法返回对象放入容器,beanId = 方法名
    public UserDao userDao(){
        UserDao userDao = new UserDao();//new用来创建bean
        return userDao;
    }

    @Bean
    public UserService userService(){
        UserService userService = new UserService();
        return userService;
    }

    @Bean //相当于<bean id = "xxx" class = "xxx"
    public UserController userController(){
        UserController userController = new UserController();
        return userController;
    }
}
public class SpringApplication {
    public static void main(String[] args) {
        //基于java config配置IOC容器的初始化
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        String[] beanId = context.getBeanDefinitionNames();

        for(String id : beanId){
            System.out.println(id+" "+context.getBean(id));
        }
    }
}

//config com.test.spring.ioc.Config$$EnhancerBySpringCGLIB$$a638b9c3@1b68b9a4
//userDao com.test.spring.ioc.Dao.UserDao@4f9a3314
//userService com.test.spring.ioc.Service.UserService@3b2c72c2
//userController com.test.spring.ioc.Controller.UserController@491666ad

20、java Config

package com.test.spring.ioc;
/**
 * java Config使用java类替代XML和注解
 */
@Configuration//当前类是一个配置类,用于替代applicationContext
@ComponentScan(basePackages = "com.test")//不但加载当前的java config,还会去加载其他类是否有注解
public class Config {
    @Bean//java config利用方法创建对象,将方法返回对象放入容器,beanId = 方法名
    public UserDao userDao(){
        UserDao userDao = new UserDao();//new用来创建bean
        return userDao;
    }

    @Bean
    @Scope("singleton")
    @Primary
    //参数名与上述beanId相同,可以完成在userService注入UserDao的操作
    public UserService userService(UserDao userDao, EmpDao empDao){
        UserService userService = new UserService();
        userService.setUserDao(userDao);
        userService.setEmpDao(empDao);//该s'g'h'y
        return userService;
    }

    @Bean //<bean id = "xxx" class = "xxx"
    public UserController userController(UserService userService){
        UserController userController = new UserController();
        userController.setUserService(userService);
        return userController;
    }
}
@Repository//使用注解进行实例化
public class EmpDao {
}

public class UserService {//使用java Config进行实例化
    private UserDao userDao;
    private EmpDao empDao;
}

21、Spring Test测试模块

Spring与JUnit整合过程

1.Maven工程依赖spring-test

2.利用@RunWith与@ContextConfiguration描述测试用例类

3.测试用例类从容器获取对象完成测试用例的执行
1.在pom.xml引入JUnit4依赖、Spring-test
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.16</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.8</version>
        </dependency>
<!--引用JUnit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
<!--            <scope>test</scope>-->
        </dependency>
    </dependencies>
import javax.annotation.Resource;
//将JUNIT4的执行权交给Spring Test,接管JUnit4的控制权在测试用例执行前自动初始化IOC容器
//将applicationContext中的<bean>对象实例化
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})//用于说明加载哪个配置文件!
public class SpringTestor {
    //在这个类运行前IOC容器已经创建好了
    //用@Resource注入属性
    @Resource
    private UserService userService;

    @Test
    public void UserService(){
        userService.createUser();
    }
}
<!--利用JUnit4测试前,实例化IOC容器的对象-->

    <bean id="userDao" class="com.test.spring.ioc.DAO.UserDao">
    </bean>

    <bean class="com.test.spring.ioc.Service.UserService" id="userService">
        <property name="userDao" ref="userDao"/>
    </bean>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值