总结:SpringIOC容器配置

IOC容器配置(所有的需要用到的类的对象配置)

假设有一个User类:

package com.spring.ioc_1;
public class User {

    private int id ;
    private String name ;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

id:表示当前实例对象在spring容器中的唯一标识。
class:这里指定是当前实例对象类的完全限定名。

    <bean id="user" class="com.spring.ioc_1.User"></bean>
看一下对象创建的个数

scope:指定作用域
默认不写scope属性,等价于“scope=singleton”单例模式
scope属性的另一个值,“scope=prototype”多例模式
如下:设置单例模式

    <bean id="user" class="com.spring.ioc_1.User" scope="singleton"></bean>

然后,从容器中获取bean实例对象

public class App {

    public static void main(String[] args) {

        //得到IOC容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从IOC容器中获得bean实例对象
        User user = (User) applicationContext.getBean("user");
        User user2 = (User) applicationContext.getBean("user");
        System.out.println(user);
        System.out.println(user2);
    }
}

结果是:

com.spring.ioc_1.User@33f88ab
com.spring.ioc_1.User@33f88ab

可以看出来是同一个对象。
模式修改为多例

    <!-- scope="prototype" 多例模式  -->
    <bean id="user" class="com.spring.ioc_1.User" scope="prototype"></bean>

还是执行刚才哪个main方法,执行结果如下:

com.spring.ioc_1.User@3b088d51
com.spring.ioc_1.User@1786dec2

可以看出来,每次调用从容器获取bean实例的方法时都会创建一个实例对象。

看一下对象创建的时机

在上述例子中的user创建默认构造函数和带参的构造函数

    public User() {
        System.out.println(">>>>>>>>>>创建了User对象");
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

在main方法中添加如下日志信息:

public class App {

    public static void main(String[] args) {

        //得到IOC容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println(">>>>>>>>>>>>>得到IOC容器");
        //从IOC容器中获得bean实例对象
        User user = (User) applicationContext.getBean("user");
        User user2 = (User) applicationContext.getBean("user");
        System.out.println(">>>>>>>>>从IOC容器中获取bean实例对象");
        System.out.println(user);
        System.out.println(user2);
    }

}

当“scope=“singleton”的时候,执行main,查看打印日志信息”

>>>>>>>>>>创建了User对象
>>>>>>>>>>>>>得到IOC容器
>>>>>>>>>从IOC容器中获取bean实例对象
com.spring.ioc_1.User@33f88ab
com.spring.ioc_1.User@33f88ab

当“scope=“prototype”的时候,执行main,查看打印日志信息”

>>>>>>>>>>>>>得到IOC容器
>>>>>>>>>>创建了User对象
>>>>>>>>>>创建了User对象
>>>>>>>>>从IOC容器中获取bean实例对象
com.spring.ioc_1.User@3b088d51
com.spring.ioc_1.User@1786dec2
从上可以总结出:

单例模式:应用只创建一个实例对象,且在容器(tomcat等)启动,Spring容器被初始化前创建的。
多例模式:应用会在对象被调用的时候才创建对象。

那么单例模式中,怎么让对象也在被调用的时候再创建?
设置“lay-init=“default””
lay-init=“default” 为“默认设置”,代表意思“不延迟初始化创建”,就是上述讲的单例模式中不写lay-init的效果。
lay-init=“true” 为“延迟初始化创建”,设置后,对象会在被调用的时候再创建。

其他参数:

init-method=“” 对象初始化的时候默认指定要调用的方法。
destroy-method=“” 对象被销毁的时候默认指定要调用的方法。

Spring IOC容器:spring的核心(作用:创建对象,处理对象的依赖关系)

IOC创建对象的几种方式:

调用无参构造:

    <bean id="user1" class="com.spring.ioc_1.User"></bean>

调用带参构造:

    <bean id="user2" class="com.spring.ioc_1.User">
        <constructor-arg value="24"  type="int" index="0"></constructor-arg>
        <constructor-arg value="科比" type="java.lang.String" index="1"></constructor-arg>
    </bean>

如上,构造函数有两个参数:
value:参数的值。
type:参数对应的数据类型。
index:参数的顺序,不写index的时候根据在标签中的先后顺序。

这里说一下另一个属性设置:ref(引用其他对象)
举例:
假设上述user2变成如下写法:

    <bean id="user2" class="com.spring.ioc_1.User">
        <constructor-arg value="24"  type="int" index="0"></constructor-arg>
        <constructor-arg  ref="lakers" index="1"></constructor-arg>
    </bean>
    <bean  id="lakers" class="java.lang.String">
            <constructor-arg  value="科比" type="java.lang.String"></constructor-arg>
    </bean>

通过工厂创建对象:
先创建工厂类:

package com.spring.ioc_1;

/**
 * @explain:UserFactory
 * @author:jimmy
 * @date:2018/12/10
 * @create by Intellij Idea
 */
public class UserFactory {

    /**
     * 非静态方法创建对象
     * @return
     */
    public User getInstance(){
        return new User() ;
    }

    /**
     * 静态方法创建对象
     * @return
     */
    public static User getInstanceByStatic(){
        return new User() ;
    }

}

(1)工厂类中,通过非静态方法创建

    <bean id="userFactory" class="com.spring.ioc_1.UserFactory"></bean>

    <bean id="user3" factory-bean="userFactory" factory-method="getInstance"></bean>

先创建工厂类,
factory-bean:指定通过哪个工厂去创建
factory-method:指定通过工厂中的哪个方法去创建对象。

(2)工厂类中,通过静态方法创建

    <bean id="user4" class="com.spring.ioc_1.UserFactory" factory-method="getInstanceByStatic"></bean>

这里:
class:为工厂类的全限定名
factory-method:指定通过class指定的工厂中的哪个静态方法去创建对象。

DI:依赖注入

(1)构造器注入
(2)set方法对属性注入
(3)通过p命名空间
……
(4)自动装配
(5)注解

模拟一个登录业务的整个处理过程:
(1)登录请求肯定是发送到action,所以需要创建一个Action,(Controller)
(2)Action中调用Service进行业务逻辑处理。
(3)Service中实际进行对数据库的操作是Dao。

UserAction:注入userService,然后调用Service中的登录业务逻辑处理

package com.spring.ioc_1;

/**
 * @explain:Action
 * @author:jimmy
 * @date:2018/12/10
 * @create by Intellij Idea
 */
public class UserAction {

    private UserService userService  ;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String login(){
        userService.toLogin() ;
        return "登录成功";
    }

}

UserService:注入UserDao,调用Dao层中的操作数据库的方法

package com.spring.ioc_1;

/**
 * @explain:
 * @author:jimmy
 * @date:2018/12/10
 * @create by Intellij Idea
 */
public class UserService {


    private UserDao userDao ;

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

    public String toLogin(){
        userDao.query() ;
        return "ok" ;
    }

}

UserDao中执行对数据库的实际操作。

要在Action中调用Service中的方法,就需要先通过set方法注入Service。【刚开始最常规的写法】

【内部bean的写法实现】

    <!--内部bean写法-->
    <bean id="userAction" class="com.spring.ioc_1.UserAction">
        <property name="userService">
            <bean class="com.spring.ioc_1.UserService">
                <property name="userDao">
                    <bean class="com.spring.ioc_1.UserDao"></bean>
                </property>
            </bean>
        </property>
    </bean>

总结:这种写法,内部bean只在bean内部有用
【p命名空间的写法】

<bean id="userDao" class="com.spring.ioc_1.UserDao" ></bean>

<bean id="userService" class="com.spring.ioc_1.UserService" p:userDao-ref="userDao"></bean>

<bean id="userAction2" class="com.spring.ioc_1.UserAction" p:userService-ref="userService"></bean>

总结:p命名空间的写法,其实是对set属性注入写法的优化
p:跟你要注入的bean的id,如果是传值的话直接“=”,如果是要引用对象的话后面要跟“ref”.

【自动装配通过byName】


    <!--自动装配的写法-->
    <bean id="userDao3" class="com.spring.ioc_1.UserDao" ></bean>
    <bean id="userService3" class="com.spring.ioc_1.UserService" autowire="byName"></bean>
    <bean id="userAction3" class="com.spring.ioc_1.UserAction" autowire="byName"></bean>

解释:在userService中,如下图,定义了userDao3,那么只要找到了bean唯一标识为userDao3的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" 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" default-autowire="byName">
        
      <!--自动装配的写法-->
    <bean id="userDao3" class="com.spring.ioc_1.UserDao" ></bean>
    <bean id="userService3" class="com.spring.ioc_1.UserService" ></bean>
    <bean id="userAction3" class="com.spring.ioc_1.UserAction" ></bean>
</beans>

需要注入的是:byName方式定义的名称和set方法注入的名称必须要一直,否则会报错。

【通过byType(根据类型)自动装配】上述中例子修改为byType即可。
通过类型自动装配的时候,需要注意IOC容器中只能有一个这种类型的对象的对象,也就是不能如下这么定义:

<bean id="userDao3" class="com.spring.ioc_1.UserDao" ></bean>
<bean id="userDao4" class="com.spring.ioc_1.UserDao" ></bean>

【缺点是】自动装配在后期项目较大的时候不利于维护。

* 注解方法:(简化Spring IOC容器的配置)

使用注解的步骤:
(1)先要引入context的命名空间:
(2)一定要开启注解扫描

@Component注解

@Component()//将一个对象加入IOC容器
@Resource(name="")//根据name属性注入,在字段上,并不是set方法,set方法就不需要了。

package com.spring.ioc_2;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @explain:userAction
 * @author:jimmy
 * @date:2018/12/10
 * @create by Intellij Idea
 */
@Component("userAction")
public class UserAction {
    @Resource(name = "userService")
    private UserService userService  ;

}
package com.spring.ioc_2;

import com.spring.ioc_1.UserDao;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @explain:1
 * @author:jimmy
 * @date:2018/12/10
 * @create by Intellij Idea
 */
@Component("userService")
public class UserService {

    @Resource(name = "userDao")
    private UserDao userDao ;

}

@Component(“userService”)可以简化为@Component,表示默认取你当前类名,并且第一个字母小写。
@Resource(name = “userDao”)可以简化为@Resource,表示默认按照userDao这个类型去查找对象,如果找到了则直接注入。不关乎名字。

缺点:@Component虽然可以在service,dao,也可以在action中完成注解,但是我们开发过程中就不能很好的区分持久层,业务层,控制层。

@Service:在业务逻辑层注解使用
@Repository:在持久层注解使用
@Controller:在控制层注解使用

注解:
可以简化配置,可以把对象加入IOC容器,处理依赖关系。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值