Spring第一天

第一个Spring程序

1、创建项目
2、导入jar包spring.jarcommons-logging.jar
3、创建一个javabean类

public class Hello {
    public void hello(){
        System.out.println("hello");
    }
}

4、在src目录下创建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
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <!-- 
        beans
            一个bean代表一个类
          所以beans就是很多个类
     -->
     <!-- 
        一个类
        id  标示符   
        class 类的全名
      -->
    <bean id="hello" class="spring.com.bxp.bean.Hello">
    </bean>
</beans>

5、创建测试类

public class Test {
    public static void main(String[] args) {
//启动spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从spring容器中提取bean
        Hello hello = (Hello) context.getBean("hello");
        hello.hello();
    }
}

IOC

概念:把对象的创建,初始化,销毁交给Spring容器来做。

Spring创建对象的方式

1、构造函数
spring内部默认调用spring的构造函数创建对象
2、静态工厂
(1)创建静态工厂

public class HelloFactory {
    public  static Hello getInstance(){
        return new Hello();
    }
}

(2)配置工厂

<?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-2.5.xsd">
    <!-- 
        beans
            一个bean代表一个类
          所以beans就是很多个类
     -->
     <!-- 
        一个类
        id  标示符   
        class 类的全名
      -->
    <bean id="hello" class="spring.com.bxp.bean.Hello">
    </bean>
    <!-- 配置静态工厂 -->
    <bean id="hello2" class="spring.com.bxp.bean.HelloFactory" factory-method="getInstance"></bean>
</beans>

(3)测试

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Hello hello = (Hello) context.getBean("hello2");
        hello.hello();
    }
}

3、实例工厂
(1)创建实例工厂(使用最多)

public class HelloFactory {
    public  Hello getInstance(){
        return new Hello();
    }
}

(2)配置实例工厂

<?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-2.5.xsd">
    <!-- 
        beans
            一个bean代表一个类
          所以beans就是很多个类
     -->
     <!-- 
        一个类
        id  标示符   
        class 类的全名
      -->
    <bean id="hello" class="spring.com.bxp.bean.Hello">
    </bean>
  
    <!-- 配置实例工厂 -->
    <bean id="helloFactory" class="spring.com.bxp.bean.HelloFactory"></bean>
    <!--  factory-bean对象工厂  factory-method对象工厂方法 -->
    <bean id="hello3" factory-bean="helloFactory" factory-method="getInstance"></bean>
</beans>

(3)测试

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Hello hello = (Hello) context.getBean("hello3");
        hello.hello();
    }
}

使用别名

在applicationContext.xml文件中使用alias标签

  <bean id="hello" class="spring.com.bxp.bean.Hello">
    </bean>
    <alias name="hello" alias="he"/>

对象的创建时机

默认创建方式
<bean id="hello" class="spring.com.bxp.bean.Hello">

1、加加载配置文件

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

2、根据配置文件中的配置的bean创建对象,配置多少个bean,创建多少个对象。

public Hello() {
        // TODO Auto-generated constructor stub
        System.out.println("构造方法 ");
    }

3、获取对象

Hello hello = (Hello) context.getBean("hello3");
延迟创建(配置lazy-init属性)
 <bean id="hello" lazy-init="true" class="spring.com.bxp.bean.Hello">

1、加加载配置文件

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

2、获取对象

Hello hello = (Hello) context.getBean("hello3");
//获取对象的同时创建对象
public Hello() {
        // TODO Auto-generated constructor stub
        System.out.println("构造方法 ");
    }
意义

如果把lazy-init值改为true,在spring启动的时候,检测不到任何问题,会存在任何问题。所以一般情况下lazy-init的值为false。
如果一个bean中包含大量的数据,不希望bean过早的停留在内存中,此时将lazy-init的值改为true

对象的scope

在默认情况下(scope为singleton)
在spring中创建的对象的单例的。将来service和dao层所有的类将放到spring中,这两层中类的实例都是单例的,不能将属性声明在属性中,会出现线程安全问题。
scope为prototype:

<bean scope="prototype" id="hello" lazy-init="false" class="spring.com.bxp.bean.Hello">

lazy-init和prototype的结合

scope为prorotype,lazy-init为true
时:在context.getBean()时候创建对象
scope为prorotype,lazy-init为false时:在context.getBean()时候创建对象,lazy-init为false失效。
scope为prorotype,始终在context.getBean()时候创建对象

对象的创建和销毁

1、创建对象

public class Hello {
    
    public void init(){
        System.out.println("初始化方法");
    }
    public void destorym(){
        System.out.println("销毁方法");
    }
    public void hello(){
        System.out.println("hello");
    }
    public Hello() {
        // TODO Auto-generated constructor stub
        System.out.println("构造方法 ");
    }
    
}

2、在配置文件中进行配置

<bean id="hello"  class="spring.com.bxp.bean.Hello"
    lazy-init="false"  init-method="init" 
    destroy-method="destorym">
执行顺序

1、调用构造函数创建对象
2、有spring内部调用init()方法进行对象的初始化
3、执行对象的方法
4、由执行context.coose()方法时候,由spring内部调用destory()方法

说明

1、init()方法由spring内部调用
2、只有在spring容器关闭的时候才会执行,一般情况下spring容器是不会关闭的,只有在web容器销毁的时候才关闭。
3、如果bean的配置为scope="prototype",则spring容器不负责销毁。

IOC执行流程

IOC执行流程

DI(依赖注入)

给属性赋值
1、创建的对象Persion

public class Persion {
    private long id;
    private String name;
    private List list;
    private Set set;
    private Map map;
    private Properties pro;
    private Hello hello;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Set getSet() {
        return set;
    }
    public void setSet(Set set) {
        this.set = set;
    }
    public Map getMap() {
        return map;
    }
    public void setMap(Map map) {
        this.map = map;
    }
    public Properties getPro() {
        return pro;
    }
    public void setPro(Properties pro) {
        this.pro = pro;
    }
    public Hello getHello() {
        return hello;
    }
    public void setHello(Hello hello) {
        this.hello = hello;
    }
}

2、在配置文件对属性进行配置

<bean id="persion" class="spring.com.bxp.bean.Persion">
      <!-- name:属性, value:值, 引用类型使用ref赋值 -->
        <property name="id" value="3"></property>
        <property name="name" value="张三"></property>
        
        <property name="hello" ref="hello"></property>
        
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
                <ref bean="hello"/>
            </list>
        </property>
        
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
                <ref bean="hello"/>
            </set>
        </property>
        
        <property name="pro">
            <props>
                <prop key="pro1">pro1</prop>
                <prop key="pro2">pro2</prop>
            </props>
        </property>
        
        <property name="map">
            <map>
                <entry key="entry1">
                    <value>entry1</value>
                </entry>
                <entry key="entry2">
                    <ref bean="hello"/>
                </entry>
            </map>
        </property>
      </bean>
      
    <bean id="hello"  class="spring.com.bxp.bean.Hello"
    lazy-init="false" init-method="init" 
    destroy-method="destorym">
    </bean>
步骤:

1、spring容器实例化persion和hello两个bean对象
2、利用java的反射机制调用setter方法对属性进行赋值。
3、调用context.getBean()获取对象。
如果配置了init()方法,则先执行setter方法,在执行init方法
persion对象依赖于hello对象,如果在hello的bean标签上面加上lazy-init = true的属性将会失效,因为创建persion对象必须创建hello对象。

使用构造器进行赋值

public Persion(long id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

在配置文件中

 <bean id="persion" class="spring.com.bxp.bean.Persion">
        <constructor-arg index="0" value="1"></constructor-arg>
        <constructor-arg index="1" type="java.lang.String" value="张三"></constructor-arg>
      </bean>

IOC和DI的意义:

实现了完全面向接口编程,客户端没有必要考虑具体的实现类是什么。

注解

概念

1、用来解释说明
2、必须作用于类的某一部分
3、注解的作用于范围(java,class,jvm)
4、注解解析器

自定义注解

类注解

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)//classInfo注解可以标注在类上
/**
 * RetentionPolicy.SOURCE 只能在源代码上使用
 *RetentionPolicy.CLASS 可以在源代码上和字节码上进行使用
 *RetentionPolicy.RUNTIME 可以使用在源代码,字节码,jvm中
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented  //该注解能够出现在帮助文档中
public @interface ClassInfo {
    String name() default "";//给该注解声明一个属性name,默认值为""
}

方法注解

@Target(ElementType.METHOD)//classInfo注解可以标注在类上
/**
 * RetentionPolicy.SOURCE 只能在源代码上使用
 *RetentionPolicy.CLASS 可以在源代码上和字节码上进行使用
 *RetentionPolicy.RUNTIME 可以使用在源代码,字节码,jvm中
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented  //该注解能够出现在帮助文档中
public @interface MethodInfo {
    String value() default "";
}

测试类

@ClassInfo(name = "这是类")
public class MyClass {
    
    @MethodInfo("这是方法")
    public void fun(){
        
    }
}

解析注解

public void parse() {
        Class clazz = MyClass.class;

        if (clazz.isAnnotationPresent(ClassInfo.class)) {
            ClassInfo classInfo = (ClassInfo) clazz
                    .getAnnotation(ClassInfo.class);
            System.out.println(classInfo.name());
        }

        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(MethodInfo.class)) {
                MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
                System.out.println(methodInfo.value());
            }
        }
    }

Spring中的注解

案例:

1、创建两个实体类Persion和Student

public class Persion {
    
    @Resource(name = "student")
    private Student student;
    public void say(){
        student.say();
    }
}


public class Student {
    public void say(){
        System.out.println("student");
    }
}

2、在配置文件中进行配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
   <bean id="persion" class="spring.com.bxp.bean.Persion"></bean>
   <bean id="student" class="spring.com.bxp.bean.Student"></bean>
   <!-- 
        启动依赖注入的注解解析器
     -->
    <context:annotation-config></context:annotation-config>
</beans>

引入依赖注入的注解解析器需要的名称空间

xmlns:context="http://www.springframework.org/schema/context"

  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-2.5.xsd"

3、测试

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Persion persion = (Persion) context.getBean("persion");
        persion.say();
    }  
注解依赖注入的步骤:

1、启动spring容器
2、spring容器内部创建两个对象(Persion和Student)
3、当spring容器解析到<context:annotation-config></context:annotation-config>时启动依赖注入解析器
4、spring容器在容器中查找所有的bean(Persion,Student)
5、查看meigebean的每个属性上是否有Resource注解
6、如果属性上面有该注解,则检查是否有name属性
7、如果没有name属性,则获取标注的属性的名称,然后将该名称和sping容器中的id进行匹配,如果匹配成功,则进行赋值。如果匹配不成功,则按照类型进行匹配,如果匹配成功则赋值,如果不成功,则报错。
8、如果有name属性,则把name属性的值解析出来,和spring容器中的id进行匹配,如果匹配成功,则赋值,如果不成功则报错。
综上所述:xml的效率高于注解,但是注解书写方便。

spring中定义的注解

1、按照类型进行匹配

@Autowired    //按照类型进行匹配

2、按照id进行匹配

@Autowired    
@Qualifier("student")

注解只能应用与引用类型。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容