Spring入门

来源:互联网 发布:php 两个日期相差天数 编辑:程序博客网 时间:2024/04/28 16:25

spring容器创建对象的3种方式(bean的实例化)  
 
    1,调用默认的构造函数(默认)  
        1)指定bean的class属性  
        2)class需要一个默认的空构造器  
          
        <bean id="helloWorld" class="com.jxn.HelloWorld" />  
          
        得到实例对象:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");  
          
    2,使用静态工厂方法  
        1)指定class属性外  
        2)通过factory-method属性来指定创建bean实例的静态工厂方法  
          
        <bean id="helloWorld" class="com.jxn.HelloWorldFactory" factory-method="createInstance"></bean>  
        注:相当于调用了 HelloWorldFactory.createInstance();  
          
        public class HelloWorldFactory {  
            public static HelloWorld createInstance(){  
                return new HelloWorld();  
            }  
        }  
          
        得到实例对象:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");  
 
    3,使用实例工厂方法  
        1)定义一个工厂类  
        2)通过factory-bean属性指定工厂类,通过factory-method属性指定该工厂类的非静态工厂方法  
 
        <bean id="helloWorldFactory" class="com.jxn.HelloWorldFactory" />  
        <bean id="HelloWorld" factory-bean="helloWorldFactory" factory-method="createInstance" />  
        注:相当于调用了 new HelloWorldFactory.createInstance();  
          
        public class HelloWorldFactory {  
            public HelloWorld createInstance(){  
                return new HelloWorld();  
            }  
        }  
          
        得到实例对象:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");  
 
    注:spring调用工厂方法,在该工厂方法中,由程序员来创建对象。


创建一个springHelloworld程序

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Spring的IOC、Spring对象初始化bean时机、Spring容器生命周期


IOC指的是控制反转,把对象的创建、初始化、销毁等工作都交给Spring容器。由spring容器来控制对象的生命周期。


Spring对象初始化bean时机:

在默认情况下,只要在Spring容器中配置了一个bean,容器在启动时就会实例化该bean,单例模式。
如果在Spring配制文件时设置懒加载模式(lazy-init=”true”),在getBean时才会实例化对象。
如果scope=”prototype”时,无论lazy-init的值是什么都只会在使用时才会创建,当struts2的
action和spring容器整合的时候,action的scope设置成prototype。

spring容器生命周期:



    启动spring容器
    创建helloWorld对象
    调用helloWorld对象的init方法,init方法是由spring容器内部调用的
    在客户端提取helloWorld对象,对象调用方法
    当spring容器关闭的时候,执行destroy方法:注意:前提条件:必须为单例,如果多实例,不起作用。


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Spring中Bean的命名

<?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">
    <bean id="helloWorld" class="reed1991.alias.HelloWorld"></bean>
    <alias name="helloWorld" alias="alias1"/>
    <alias name="helloWorld" alias="alias2"/>
    <alias name="helloWorld" alias="alias3"/>

</beans>


此时,helloWorld为标识符,而alias1,alias2,alias3为别名,它们都可以作为Bean的键值;


HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
 HelloWorld helloWorld2 = (HelloWorld)context.getBean("alias2");

这两个语句将会等价

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

spring中的scope

1.在默认情况下,spring创建bean是单例模式

HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
        helloWorld.getLists().add("aa");
 
        
        HelloWorld helloWorld2 = (HelloWorld)context.getBean("helloWorld");
        helloWorld2.getLists().add("bb");
      
        System.out.println(helloWorld.getLists().size());
        System.out.println(helloWorld2.getLists().size());

则打印的都是2,因此在默认情况下,spring创建bean是单例模式.singleton  默认,

属性是共享的,所以一般情况下把数据存放在方法中的变量中.



修改applicationContext.xml

<bean id="helloWorld"  class="reed1991.scope.HelloWorld" scope="prototype" ></bean>

则打印的都是1,所以,其变为多例


<bean id="helloWorld"  class="reed1991.scope.HelloWorld" scope="prototype" ></bean>和

<bean id="helloWorld"  class="reed1991.scope.HelloWorld" scope="prototype" lazy-init="false"></bean>

    当一个bean是多例模式的情况下,lazy-init为false或者default无效



init-method
                     * 该方法是由spring容器执行
                     * 在构造函数之后执行
                     * 如果在构造函数之后,在调用方法之前要做一些工作,可以在init方法中完成

destroy-method
                     * 如果该bean是单例,则在spring容器关闭或者销毁的时候,执行该方法
                     * 如果该bean是多例,则spring容器不负责销毁
                   说明:要想让spring容器控制bean的生命周期,那么该bean必须是单例
                              如果该bean是多例,该bean中还有资源,关闭资源的操作由程序员完成


Spring注解@Scope("prototype")

Spring在Action上面注解@Scope("prototype")

表示每次接收一个请求创建一个Action对象..

如若改成其他,例如单例模式,则很多请求公用同一个Action.

一个注册的例子,如果没加上这个注解,注册完成后,下一个请求再注册一次,Action里会保留上一次注册的信息..

-----------------------------------------------------------------------------------------------------------------------------------------------------

springDI(依赖注入):给属性赋值就为依赖注入


1.Set方法注入


public classPerson{

    private Long pid;//代表基本类型的包装类

    private String pname;//String类型

    private Student student;//引用类型

    private List lists;

    private Set sets;

    private Map map;

    private Properties properties;

    //setget方法

}



<?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">
    <bean id="person" class="reed1991.set.Person">
        <!--
            property就是代表属性
              在spring中基本类型(包装类型和String)都可以用value来赋值
                                     引用类型用ref赋值
         -->
        <property name="pid" value="5"></property>
        <property name="pname" value="reed1991"></property>
        <property name="student">
            <ref bean="student"/>
        </property>
        <property name="lists">
            <list>
                <value>list1</value>
                <value>list2</value>
                <ref bean="student"/>
            </list>
        </property>
        <property name="sets">
            <set>
                <value>set1</value>
                <value>set2</value>
                <ref bean="student"/>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="map1">
                    <value>map1</value>
                </entry>
                <entry key="map2">
                    <value>map2</value>
                </entry>
                <entry key="map3">
                    <ref bean="student"/>
                </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="prop1">
                    prop1
                </prop>
            </props>
        </property>
    </bean>
    <bean id="student" class="reed1991.di.xml.set.Student"></bean>

</beans>


2.构造方法注入

public Person(Long pid,String pname){
        this.pid = pid;
        this.pname = pname;
    }
    
    public Person(String pname,Student student){
        this.pname = pname;
        this.student = student;
    }

<bean id="person" class="reed.constructor.Person">
        <!--
            构造函数的参数
              index  第几个参数,下标从0开始
              type   参数的类型
              ref    如果类型是引用类型,赋值
              value  如果类型是基本类型,赋值
             说明:
                只能指定一个构造函数
         -->
        <constructor-arg index="0"  type="java.lang.String" value="reed1991"></constructor-arg>
        <constructor-arg index="1"  ref="student"></constructor-arg>

<!--则调用第二个构造函数-->   

</bean>
    
    <bean id="student" class="reed.constructor.Student"></bean>
</beans>



iocdi做了什么事情呢?

  *  创建对象

  * 给属性赋值

iocdi的意义:

   可以在一个类中引入一个接口,而给接口赋值的工作交给spring容器来做,程序员只需要在配置文件做一些配置就可以了,这样在客户端做到了完全的面向接口编程



例子

Person.java

package reed.set;public class Person {private Long pid;private String pname;        public Long getPid() {        return pid;    }       public void setPid(Long pid) {this.pid = pid;}public String getPname() {return pname;}public void setPname(String pname) {this.pname = pname;}}


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">                      <bean id="person" class="reed.Person">                      <property name="pid" value="5"></property>                      <property name="pname" value="王二麻子"></property>               </bean>                      </beans>


PersonTest.java

import cn.itcast.spring.utils.SpringHelper;public class PersonTest extends SpringHelper{static{path = "reed/applicationContext.xml";}   @Testpublic void test(){Person person=(Person)context.getBean("person");System.out.println(person.getPid());System.out.println(person.getPname());}}

控制台输出

5
王二麻子


通过构造函数赋值

Person.java

package reed.constructor;public class Person {private Long pid;private String pname;private Student student;public Person(Long pid,String pname,Student student){this.pid=pid;this.pname=pname;this.student=student;}public Long getPid() {return pid;}public String getPname() {return pname;}public Student getStudent() {return student;}}

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

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">           <!--             构造函数的参数              index  第几个参数,下标从0开始              type   参数的类型              ref    如果类型是引用类型,赋值              value  如果类型是基本类型,赋值             说明:                只能指定一个构造函数         -->         <bean id="person" class="reed.constructor.Person">          <constructor-arg index="0" type="java.lang.Long" value="5"></constructor-arg>          <constructor-arg index="1" type="java.lang.String" value="reed"></constructor-arg>           <constructor-arg index="2" ref="student1"></constructor-arg>           </bean>               <bean id="student1" class="reed.constructor.Student"></bean>           </beans>

PersonTest.java
public class PersonTest extends SpringHelper{static{path = "reed/constructor/applicationContext.xml";}@Testpublic void test(){Person person = (Person)context.getBean("person");        person.getStudent().say();System.out.println(person.getPname());System.out.println(person.getPid());}}

控制台输出

student
reed
5

-----------------------------------------------------------------------------------------------------------------------------------

spring使用注解进行DI(依赖)注入

Person.java

public class Person {//@Resource(name="")这三条是等价的//@Resource()@Resource(name="student1")private Student studen;public void say(){this.studen.say();}}

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

applicationContext.xml
<?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">                  <context:annotation-config></context:annotation-config>                 <bean id="student1" class="reed.annotation.Student"></bean>         <bean id="person" class="reed.annotation.Person"></bean>                          </beans>

PersonTest.java

public void test(){ClassPathXmlApplicationContext applicationContext=(ClassPathXmlApplicationContext)context;Person person=(Person)applicationContext.getBean("person");person.say();applicationContext.close();}

/**
 * 原理
 *    *  启动spring容器,并且加载配置文件
 *    *  会为student和person两个类创建对象
 *    *  当解析到<context:annotation-config></context:annotation-config>
 *       会启动依赖注入的注解解析器
 *    *  会在纳入spring管理的bean的范围内查找看哪些bean的属性上有@Resource注解
 *    *  如果@Resource注解的name属性的值为"",则会把注解所在的属性的名称和spring容器中bean的id进行匹配
 *       如果匹配成功,则把id对应的对象赋值给该属性,如果匹配不成功,则按照类型进行匹配,如果再匹配不成功,则报错
 *    *  如果@Resource注解的name属性的值不为"",会把name属性的值和spring容器中bean的id做匹配,如果匹配
 *       成功,则赋值,如果匹配不成功 ,则直接报错

-------------------------------------------------------------------------------------------------------------------------------------------

spring scan

原理
 *   *  1.启动spring容器,加载配置文件
 *   * 2. spring容器解析到
 *         <context:component-scan base-package="reed.scan"></context:component-scan>
 *   *  3.spring容器会在指定的包及子包中查找类上是否有@Component
 *   *  如果@Component注解没有写任何属性
 *        @Component
 *        public class Person{
 *        
 *        }
 *        ==
 *        <bean id="person" class="..Person">
 *      如果@Component("aa")
 *        @Component
 *        public class Person{
 *        
 *        }
 *        ==
 *        <bean id="aa" class="..Person">
 *    *  在纳入spring管理的bean的范围内查找@Resource注解
 *    *  执行@Resource注解的过程
 *  说明:
 *     xml效率比较高,但是书写比较麻烦

 *     注解效率比较低,书写比较简单


package reed.scan;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;@Component("perso")public class Person {@Resource(name="student")private Student studen;private Long pid;public void say(){this.studen.say();}@PostConstructpublic void init(){System.out.println("init");}@PreDestroypublic void destroy(){System.out.println("destroy");}}

package reed.scan;import org.springframework.stereotype.Component;@Componentpublic class Student {public void say(){System.out.println("student");}}

import org.junit.Before;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringHelper{public static ApplicationContext context;public static String path;@Beforepublic void startSpring(){context = new ClassPathXmlApplicationContext(path);}}
<?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"><!-- 1、导入命名空间 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 2、启动类扫描的注解解析器3、启动依赖注入的注解解析器--><!-- component就是beanbase-package   会在base-package的值所在的包及子包下扫描所有的类 --><context:component-scan base-package="reed.scan"></context:component-scan></beans>

package reed.scan;import org.junit.Test;import org.springframework.stereotype.Component;import reed.SpringHelper;public class PersonTest extends SpringHelper{static{path = "reed/scan/applicationContext.xml";}@Testpublic void test(){Person person = (Person)context.getBean("perso");person.say();}}
输出

init
student

  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Spring中mvc三层用注解写

说明:如果一个类中有基本类型,并且基本类型是用spring的形式赋值的,这个时候,该类必须用xml来完成,不能用注解

一、基于@Component注解的配置

sprin2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。

这 3 个注释和 @Component 是等效的,不过分开成这三个层次更清晰

1、@controller 控制器(注入服务)   表示层
2、@service 服务(注入dao)             业务逻辑层
3、@repository dao(实现dao访问)   数据访问层

package reed.annotation;import javax.annotation.Resource;import org.springframework.stereotype.Controller;@Controller("personAction")public class PersonAction {@Resourceprivate PersonService personService;public void savePerson(){this.personService.savePerson();}}

package reed.annotation;import org.springframework.stereotype.Repository;@Repository("personDao")public class PersonDaoImpl implements PersonDao{@Overridepublic void savePerson() {System.out.println("save person");}}

package reed.annotation;import javax.annotation.Resource;import org.springframework.stereotype.Controller;@Controller("personAction")public class PersonAction {@Resourceprivate PersonService personService;public void savePerson(){this.personService.savePerson();}}


package reed.annotation;import org.junit.Test;import reed.utils.SpringHelper;public class PersonTest extends SpringHelper{static{path="reed/annotation/applicationContext.xml";}@Testpublic void test(){PersonAction personAction=(PersonAction)context.getBean("personAction");personAction.savePerson();}}

ersion="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"><context:component-scan base-package="reed.annotation"></context:component-scan></beans>

输出save person


Spring中的持久层数据访问Dao注解这样使用@Repository(exampleDao),括号里的值是代表什么起什么作用,也可以单独使用@Repository不加边的东西,

问题是加了后边有什么好处?

就是bean的名称,如果不加括号里面的spring管理的bean默认及时类名首字母小写,
好处就是如果有多个同一个类型的bean,可以加上名称自己区分,举个例子吧
一个接口有多个实现类,因为spring注入默认按类型查找,只是注入就要报错,你给每个实现类上的bean加上名字,

注入的时候再加上@Qualifier(你要注入bean的名称)就行了

--------------------------------------------------------------------------------------------------------------------------------------

AOP的一些概念

切面

        日志、安全性的框架、权限的检查等,总之和业务逻辑没有关系的都可以看做切面

    通知

        切面中的方法


    切入点

        只有符合切入点,才能把通知和目标方法结合在一起


    连接点

        客户端调用的方法


     织入: 形成代理方法的过程


    * 代理对象的方法=通知+目标方法

    aop:做到了代码块的重用


-----------------------------------------------------------------------------------------------------------------------------------

Spring切入点表达式常用写法

Spring AOP 用户可能会经常使用 execution切入点指示符。执行表达式的格式如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

modifiers-pattern:修饰符

ret-type-pattern:返回值

declaring-type-pattern?访问权限

name-pattern:方法名

(param-pattern):参数

throws-pattern?:异常


任意公共方法的执行:

execution(public * *(..))

任何一个名字以“set”开始的方法的执行:

execution(* set*(..))

AccountService接口定义的任意方法的执行:

execution(* com.xyz.service.AccountService.*(..))


在service包中定义的任意方法的执行:

execution(* com.xyz.service.*.*(..))

在service包或其子包中定义的任意方法的执行:

execution(* com.xyz.service..*.*(..))

-----------------------------------------------------------------------------------------------------------------------------

spring中注解

Spring中什么时候用@service,什么时候用@Resource

当你需要定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类定义为一个bean,bean名称为XXX;

当需要在某个类中定义一个属性,并且该属性是一个已存在的bean,要为该属性赋值或注入时在该属性上一行使用@Resource(name="xxx"),相当于为该属性注入一个名称为xxx的bean。

@Autowire注解和@Resource一样,同样也可以标注在字段或属性的setter方法上,但它默认按类型装配。

@Transactional(readOnly=true)表明所注解的方法或类只是读取数据。
@Transactional(readOnly=false)表明所注解的方法或类是增加,删除,修改数据。

---------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------

0 0
原创粉丝点击