首页 > 编程语言 > 详细

java-spring

时间:2020-07-04 15:55:23      阅读:48      评论:0      收藏:0      [点我收藏+]

 

 

 

Spring-IOC

ioc概念

控制反转

把对象创建和对象之间的调用过程,交给Spring 进行管理。

目的就是,为了降低耦合度,因为当你想在一个类当中调用另外一个类的方法,你需要获得另外一个类的实例

 

 

IOC的底层原理:
包括xml解析,工厂模式,反射

 

技术分享图片

 

 引入工厂模式之后:

技术分享图片

 

 

IOC解耦过程

技术分享图片

 

 

IOC接口:

1Ioc思想基于IOC容器完成,IO容器底层就是对象工厂
2Spring提供IOC容器实习两种方式:两个接口

1)BeanFactory :IOC容器基本实现,Spring内部的使用接口,不提供给开发人员进行使用

2)ApplicationContext :BeanFactory接口的子接口,提供更强大的功能,一般开发人员使用


区别:
BeanFactory 加载配置文件的时候不会创建对象,在获取对象的时候才创建。

ApplicationContext ,加载文件的时候,会将配置文件里面的对象进行创建。

获取IOC容器的方式

通过beanFactory

技术分享图片

通过applicationContext获取

技术分享图片

3 ApplicationContext接口实现类

技术分享图片

 

 FileSystemXmlApplicationContext从盘符路径开始查找配置文件,绝对路径

ClassPathXmlApplicationContext项目路径下查找-----一般使用

 

 

IOC操作Bean管理
Bean管理是什么:

1Spring创建对象
2Spring注入属性

Bean管理操作两种方式

基于xml配置文件方式实现
基于注解方式实现

 

JOC操作Bean管理--基于xml方式

基于xml方式创建对象

</bean>
<bean id="usert" class="com.quan.Usert" >
</bean>

1)在sprin配置文件中,使用bean标签,标签理添加相应的属性,就可以实现对象创建

2)bean标签的属性

id:属性 =唯一标识

class属性=类的全路径

 3)默认使用无参构造方法完成对象的创建

bean的作用域

单例 - 每个Spring IoC 容器返回一个bean实例 singleton
原型- 当每次请求时返回一个新的bean实例 prototype
请求 - 返回每个HTTP请求的一个Bean实例
会话 - 返回每个HTTP会话的一个bean实例
全局会话- 返回全局HTTP会话的一个bean实例 

默认是单例 

 

技术分享图片

 

     ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
        for (int i = 0; i < 3; i++) {
            User user = (User)ac.getBean("user");
            System.out.println(user);
        }

 singleton作用域

共享一个实例bean,只创建一个实例,

 结果为:

/*socpe为sigleon的时候
com.quan.User@67784306
com.quan.User@67784306
com.quan.User@67784306
 */

prototype作用域

每次注入这个类的时候,都创建一个实例

v/*socpe为prototype的时候
com.quan.User@63753b6d
com.quan.User@6b09bb57
com.quan.User@6536e911
 */

bean标签的属性init-method= destroy-method=

 

先说两个接口先:

InitializingBean DisposableBean 标记接口 ,
主要实现Spring 执行bean时的初始化和销毁时某些方法

实现InitializingBean ,需要实现afterPropertiesSet,就是设置所有的属性之后做什么
实现DisposableBean 实现destory(),就是Spring 容器释放该bean之后做些什么

public class InitialDisp implements InitializingBean, DisposableBean {

    public void destroy() throws Exception {
        System.out.println("destroy");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("afterProper");
    }
}

 执行:

public class BETest {
    public static void main(String[] args) {
        /*
        ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable
        ApplicationContext:应用上下文
        Lifecycle:负责context的生命周期进行管理,提供start(),stop() 以及isRunning()
        Closeable:用于关闭组件,释放资源
        ConfigurableApplicationContext 接口的作用就是设置上下文 ID,设置父应用上下文,添加监听器,刷新容器,关闭,判断是否活跃等方法
         */
        ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
        InitialDisp id = (InitialDisp)ac.getBean("initdesp");
        System.out.println(id);
        ac.close();
    }
}
/*
re:
afterProper
com.quan.hll.InitialDisp@1f36e637
destroy
 */

但是不建议使用这两个接口

 

可以指定类中的某个方法为两个阶段的方法:init-method= destroy-method=

上面的类不在继承那两个接口

再bean配置文件当中:

 <bean id="initdesp" class="com.quan.hll.InitialDisp" init-method="afterPropertiesSet" destroy-method="destroy"></bean>
建议使用init-method 和 destroy-methodbean 在Bena配置文件,而不是执行 InitializingBean 和 DisposableBean 接口,也会造成不必要的耦合代码在Spring。
 

 设置bean加载和销毁所调用的方法

</bean>
<bean id="usert" class="com.quan.Usert" init-method="init" destroy-method="destroy">
</bean>

test;

      ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");

        Usert usert = (Usert)ac.getBean("usert");
        usert.say();
        //关闭ioc容器
        ((ClassPathXmlApplicationContext) ac).close();

技术分享图片

 

 

基于xml方式注入属性

1)DI: 依赖注入,就是注入属性,是IOC的一种实现方式

依赖注入-setter方法;

 11类需要各个属性的set方法

22配置文件中先创建对象,再注入属性

技术分享图片

 

 

 

 依赖注入---构造方法

1)需要创建有参构造函数

2)配置文件中使用constructor-arg标签 

第一个类:

技术分享图片View Code

第二个类:

技术分享图片View Code

spring-config.xml配置

<!--    创建User对象,id是这个资源的唯一表示-->
<bean id="user" scope="prototype" class="com.quan.User">
<!--    通过构造方法注入-->
    <constructor-arg index="0" value="QQgou"/>
    <constructor-arg index="1" ref="usert"/>
<!--    这里的user实例里面的name属性会被下面的设置替代,如果没有就是构造器的值-->
    <property name="name">
        <value>QQSpring</value>
    </property>
<!--  name这里是指User类里面的属性usert  这里的ref是指下面的bean-->
    <property name="usert" ref="usert">
    </property>
</bean>
<bean id="usert" class="com.quan.Usert" init-method="init" destroy-method="destroy">
</bean>

re;

init see you
how to sayQQSpring
see you

注:加颜色就是通过构造方法注入的形式,里面还有属性是其他类的设置

 技术分享图片

 

 

 

IOC操作Bean管理-xml注入其他类型属性

 字面量

 null值

 再熟悉值里面不要设置value属性,直接加入null标签

    <bean id="user" class="com.quan.hlll.User">
        <property name="name">
            <null></null>
        </property>
    </bean>

特殊符号<<>>

进行转义操作

    <bean id="user" class="com.quan.hlll.User">
        <property name="name" value="&lt;&gt;<<南京>>"></property>
    </bean>

技术分享图片

 

 

 

把带特殊符号内容写到CDATA

    <property name="name">
            <value><![CDATA[<<南京>>]]></value>
        </property>

注入属性-外部bean

person累有一个属性为hello对象类型

     <bean id="person" class="com.quan.hll.javaConfig.Person.Person">
          <constructor-arg index="0" value="QQQ"/>
          <constructor-arg index="1" ref="hello" />
     </bean>
     <bean id="hello" class="com.quan.hll.javaConfig.Hello.Hello"></bean>

 

技术分享图片

 

注意属性-内部bean和级联赋值

 

技术分享图片View Code

 

通过构造函数(其实set方法也是可以的)

     <bean id="person" class="com.quan.hll.javaConfig.Person.Person">
          <constructor-arg index="0" value="QQQ"/>
          <constructor-arg index="1" >
               <bean class="com.quan.hll.javaConfig.Hello.Hello"></bean>
          </constructor-arg>
     </bean>

 

 

 

 

 内部定义的累有属性的时候

注意:建议在类的内部进行内部类的定义:

 <bean id="person" class="com.quan.hll.javaConfig.Person.Person">
          <constructor-arg index="0" value="QQQ"/>
          <constructor-arg index="1" >
              <bean class="com.quan.hll.javaConfig.Hello.Hello">
                   <property name="msg">
                        <value>ourmsg</value>
                   </property>
              </bean>
          </constructor-arg>
     </bean>

 技术分享图片

 

bean属性值的注入两种xml格式

技术分享图片View Code

 

<!--     使用属性标签property其的下级value属性进行值的注入,-->
     <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" >
          <property name="name" >
               <value>quan</value>
          </property>
          <property name="addr">
               <value>gd</value>
          </property>
          <property name="age">
               <value>23</value>
          </property>
     </bean>

 

<!--     使用快捷方式进行值的注入,-->
     <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" >
          <property name="age" value="23"/>
          <property name="addr" value="gd"/>
          <property name="name" value="q1234"/>
     </bean>

 

IOC操作Bean管理(xml-注入集合属性)

 

格式:

<list value-type="java.lang.String">
    <value>list里面的元素</value>
        ...
</list>

<set>
    <value>set元素</value>
            ...
</set>


<map>
    <entry key=key值 value=key值对应的value/>
    ....
</map>


<props>
    <prop key=key值>value值写这里</prop>
            .....
</props>

 

 

eg

技术分享图片
<bean id="springlist" class="com.quan.hll.List.SpringList">
<!--          list-->
          <property name="lists" >
               <list value-type="java.lang.String">
                    <value>quan</value>
                    <value>quan</value>
                    <value>quan2</value>
               </list>
          </property>
<!--          set-->
          <property name="sets">
               <set>
<!--                    因为set属性不允许重复,只保留一个-->
                    <value>quan</value>
                    <value>quan</value>
                    <value>quan2</value>
               </set>
          </property>
<!--          Map-->
          <property name="maps">
               <map>
<!--                    同样只保留后者-->
                    <entry key="one" value="QQQ"/>
                    <entry key="one" value="ZZZ"/>
                    <entry key="two" value="ZZZ"/>
               </map>
          </property>
<!--          properties-->
          <property name="properties">
               <props>
                    <prop key="quan">shige213</prop>
                    <prop key="zhi">shige321</prop>
               </props>
          </property>
     </bean>
View Code

 

类:

 

package com.quan.hll.List;

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

public class SpringList {
    private List<Object> lists;
    private Set<Object> sets;
    private Map<Object,Object> maps;
    private Properties  properties;

    public List<Object> getLists() {
        return lists;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public Set<Object> getSets() {
        return sets;
    }

    public void setSets(Set<Object> sets) {
        this.sets = sets;
    }

    public Map<Object, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<Object, Object> maps) {
        this.maps = maps;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

 

打印类:

[quan, quan, quan2]
{one=ZZZ, two=ZZZ}
{quan=shige213, zhi=shige321}
[quan, quan2]

 

 

spring注入日期:

     <bean id="sdate" class="com.quan.hll.List.Sdate">
<!--          使用下面会报错,必须使用格式话进行格式话-->
<!--          <property name="date" value="2020-12-20"/>-->
<!--          Cannot convert value of type [java.lang.String] to required type -->
<!--          [java.util.Date] for property date: no matching edit-->
               <property name="date">
                    <bean factory-bean="dataFormat" factory-method="parse">
                         <constructor-arg value="2020-12-20"></constructor-arg>
                    </bean>
               </property>
     </bean>

     <bean id="dataFormat" class="java.text.SimpleDateFormat">
          <constructor-arg value="yyyy-MM-dd"/>
     </bean>

 

re:Sdate{date=Sun Dec 20 00:00:00 CST 2020}

 

 

 

 

PropertyPlaceholderConfigurer映射

用于配置文件的管理,

 

datasource.properties

driver=com.jdbc.mysql.connection
url=jdbc:mysql:localhost:3306
username=root
password=2009

 

<!--     加载PropertyPlaceholderConfigurerbean,并指定文件位置-->
     <bean  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          <property name="location">
               <value>datasource.properties</value>
          </property>
     </bean>

     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <property name="driverClassName" value="${driver}"/>
         <property name="username" value="${username}"/>
         <property name="password" value="${password}"/>
         <property name="url" value="${url}"/>
     </bean>

 

spring-bean的继承

这里不是在java下创建类去extend而是通过bean的配置文件去实现

主要是bean父设置一个模板或者属性,子bean公用这个属性或者模板

 

类:

public class BasePlace  {
    private String place;
    private String name;

 

下面父bean只是共享自己的name的属性值

    <bean id="base" class="com.quan.hll.expand.BasePlace" >
        <property name="name" value="Q"/>
    </bean>

    <bean id="expandbase" parent="base">
        <property name="place" value="sz"/>

    </bean>

注意:其实expandbase这个bean也是com.quan.hll.expand.BasePlace类

 

加入下面的这个bean标签的属性是说明父bean不可被实例化:

 <bean id="base" class="com.quan.hll.expand.BasePlace" abstract="true">

如果调用:
BasePlace bb = (BasePlace)ac.getBean("base");

报错

 

加入下面一句,子类bean新设置的属性值会覆盖父bean

 <property name="name" value="QQ"/>

BasePlace{place=‘sz‘, name=‘Q‘}

 

 

 

 

@Required注解依赖检查,指定类中的属性检查,部分!!!

单单加入这个还是不生效,需要在bean.xml文件里面引入解析注解的bean

适用于bean属性setter方法,并表示受影响的bean属性必须在XML配置文件在配置时进行填充。否则,容器会抛出一个BeanInitializationException异常。

 

public class BasePlace  {
    private String place;
    private String name;


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

bean。xml

    <bean id="base" class="com.quan.hll.expand.BasePlace" >
        <property name="place" value="ShenZhen"/>
    </bean>

 

baocuo

org.springframework.beans.factory.BeanInitializationException:
 Property ‘name‘ is required for bean ‘base‘

 

注册一个RequiredAnnotationBeanPostProcessor以了解在bean配置文件@Required注解

111

设置context:

<context:annotation-config/>

22设置bean

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

 

 

自定义@required注解名字(换名字)

编写注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyRequired {
}

 

注册注解:

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
    <property name="requiredAnnotationType" value="com.quan.hll.MyRequired"></property>
</bean>

 

使用即可:

public class BasePlace  {
    private String place;
    private String name;


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

 

 

 

 

 

 

 

 

使用javaConfig(注解)代替spring-config.xml来配置bean

 

/*
通过java类来加载bean,注解
 */

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HelloConfig {
    @Bean(name = "hello")
    public Hello hello(){
        return new Hello();
    }
}

相当于:

 <bean id="hello" class="com.quan.hll.javaConfig.Hello" ></bean>

 

        //通过JavaConfig的类对象来获取ApplicationConext
//        ApplicationContext ac = new AnnotationConfigApplicationContext(HelloConfig.class);
        //通过spring-config.xml配置文件来进行bean加载
        ApplicationContext ac =  new ClassPathXmlApplicationContext("spring-config.xml");

 

 

 

多个bean模块化设置配置文件

 

技术分享图片

 

 

 

 

 

 

多个构造函数的歧义

package com.quan.hll.manyConstruntor;

public class MConstructor{
    private  String name;
    private int age;
    private String addr;

    /*
    两个构造函数,可能会出现起义
     */
    public MConstructor(int age, String name,  String addr) {
        this.name = name;
        this.age = age;
        this.addr = addr;
    }

    public MConstructor(String name, int age, String addr) {
        this.name = name;
        this.age = age;
        this.addr = addr;
    }


    @Override
    public String toString() {
        return "MConstructor{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ", addr=‘" + addr + ‘\‘‘ +
                ‘}‘;
    }
}

/*
第一次没有指定类型出现这个结果:
MConstructor{name=‘23‘, age=199, addr=‘123‘}
 */

 

<!--     两个构造函数,可能会出现起义-->
<!--     <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" >-->
<!--          <constructor-arg >-->
<!--               <value>199</value>-->
<!--          </constructor-arg>-->
<!--          <constructor-arg>-->
<!--               <value>23</value>-->
<!--          </constructor-arg>-->
<!--          <constructor-arg>-->
<!--               <value>123</value>-->
<!--          </constructor-arg>-->
<!--     </bean>-->

<!--     为构造函数指定的确切数据类型,-->
     <bean id="mconstructor" class="com.quan.hll.manyConstruntor.MConstructor" >
          <constructor-arg type="java.lang.String" >
               <value>199</value>
          </constructor-arg>
          <constructor-arg type="int">
               <value>23</value>
          </constructor-arg>
          <constructor-arg type="java.lang.String">
               <value>123</value>
          </constructor-arg>
     </bean>

 

 

 

多个配置文件归结到一个配置文件

 

     <import resource="hello-config.xml"/>
     <import resource="person-config.xml"/>

 

 

 

 


SpEL(Spring Expression Language),

 

java-spring

原文:https://www.cnblogs.com/java-quan/p/13226782.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!