spring

ioc 和aop是spring的核心

spring整合其他技术,例如jdbc,mybtis,hibernate,struts等。

 

spring ioc应用

a。管理对象

  创建,初始化,释放资源,销毁

b。维护对象关系

c。搭建SpringIOC开发环境,引入jar包,在src添加applicationContext.xml

spring模块需要的jar包:

ioc:commons-logging,spring-beans,spring-context,spring-core,spring-expression

aop:aopaliance,aspectjweaver,spring-aop,spring-aspects

dao:spring-jdbc,spring-tx

dbcp:commons-collections,commons-dbcp,commons-pool

json:jackson-annotation,jackson-core,jackson-databind

webmvc:spring-web,spring-webmvc

 

servlet用到的json包(springmvc不用这些):commons-beanutil,commons-collections,commons-lang,commons-logging,ezmorph,json-lib

 


例子,管理对象的三种方式:

java代码:

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

Calendar c1=ac.getBean("c1",Calendar.class);

Calendar c2=ac.getBean("c2",Calendar.class);

Date date=ac.getBean("date",Date.class);

System.out.println(c2);

applicationContext.xml:

<!-- 采用new GregorianCalendar(),构造方法 -->

<bean id="c1" class="java.util.GregorianCalendar"></bean>

<!-- 采用Calendar.getInstance(),静态工厂方法 -->

<bean id="c2" class="java.util.Calendar" factory-method="getInstance"></bean>

<!-- 采用c2.getTime(),对象工厂方法 -->

<bean id="date" factory-bean="c2" factory-method="getTime"></bean>

 


 

2.Spring创建Bean对象的控制

a.控制对象创建方式(使用范围)

在<bean> 元素中使用scope属性控制。scope可以支持singleton或prototype。默认值是singleton单例模式

  <bean scope="singleton">该组件在spring容器里只有一个bean对象。

  <bean scope="prototype">该组件每次ac.getBean("id")返回不同的bean对象。

b。指定对象初始化操作。

  假设对象里有个init()方法,public void init(){xxxxx};让t1这个实例对象一创建完,自动调用init方法。
  <bean id="t1" class="org.alexhe.bean.Test" init-method="init"></bean>

c。指定对象销毁时操作:(比较少用)并需要满足条件才有效:1,组件为单例模式。2,调用AbstractApplicationContext容器对象的close()方法

  假设对象里有个mydestroy方法,public void mydestroy(){xxxxx};让t1这个实例对象一旦销毁,自动调用mydestroy方法。

  <bean id="t1" class="org.alexhe.bean.Test" destroy-method="mydestroy"></bean>

d。控制单例对象创建时机。 不在容器一开始建立时创建对象,而是在ac.getBean("t1",Test.class)时才创建对象。

<bean id="t1" class="org.alexhe.bean.Test" destroy-method="mydestroy" lazy-init="true"></bean>


 

ioc信息set注入,管理关系,set注入和构造器注入:

java类:

public class Computer {

private String cpu;

private String hdd;

private String mainboard;

public void show(){

System.out.println("cpu:"+cpu);

System.out.println("hdd:"+hdd);

System.out.println("mainboard:"+mainboard);

}

//省略get set方法

}

xml:

<bean id="p1" class="org.alexhe.bean.Computer">

<!-- 信息set注入 -->

<property name="cpu" value="骁龙"></property>

<property name="hdd" value="希捷"></property>

<property name="mainboard" value="华硕"></property>

</bean>

测试类:

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

Computer c=ac.getBean("p1",Computer.class);

c.show();

 

构造器注入:

javaBean:

public Computer(String cpu,String hdd){

this.cpu=cpu;

this.hdd=hdd;

}

xml:

<bean id="p2" class="org.alexhe.bean.Computer">

<!-- 构造器注入 -->

<constructor-arg index="0" value="高通"></constructor-arg>

<constructor-arg index="1" value="2G"></constructor-arg>

</bean>

测试类:

Computer c=ac.getBean("p1",Computer.class);

c.show();

 

组件注入:student需要一个computer组件

javaBean:

public class Student {

private Computer c;

public void show(){

c.show();

}

public Computer getC() {

return c;

}

public void setC(Computer c) {

this.c = c;

}

 

}

xml:

<bean id="p1" class="org.alexhe.bean.Computer">

<!-- 信息set注入 -->

<property name="cpu" value="骁龙"></property>

<property name="hdd" value="希捷"></property>

<property name="mainboard" value="华硕"></property>

</bean>

<bean id="p2" class="org.alexhe.bean.Computer">

<!-- 构造器注入 -->

<constructor-arg index="0" value="高通"></constructor-arg>

<constructor-arg index="1" value="2G"></constructor-arg>

</bean>

 

<bean id="s1" class="org.alexhe.bean.Student">

<!-- 利用set注入Computer -->

<property name="c" ref="p1"></property>

</bean>

测试类:

Student s=ac.getBean("s1",Student.class);

s.show();

 

 


 

unit02_1

1.自动注入=自动装配,简化注入配置,byType,byName,constructor

autowire="byType",按类型匹配,同类型只能出现一次。Student需要Computer组件,所以computer的注入只能出现一次。

<bean id="s2" class="org.alexhe.bean.Student" autowire="byType"></bean>

byName,按名字匹配,名字要和set方法的缩写一样。

 

2.各种类型信息的注入配置格式

a。注入字符串,数值单个数值

  <property name="" value="">

b。注入bean对象

c。注入集合list,set,map,properties

d。spring表达式注入,#{表达式}   #{id名.属性}或者#{id名.key}。如果是对象属性,需要有getXXX方法。

 

日期例子:主意用的是java.sql.date,特殊情况,这种例子以后用的不多。

import java.sql.Date;

 

public class MessageBean {

private String name;

private int age;

private Date birth;

public void show(){

System.out.println("name:"+name);

System.out.println("age:"+age);

System.out.println("birth"+birth);

}

public void setName(String name) {

this.name = name;

}

public void setAge(int age) {

this.age = age;

}

public void setBirth(String birth) {

Date date=Date.valueOf(birth);

this.birth = date;

}

 

}

xml:注意传入的是字符串

<bean id="msg" class="org.alexhe.bean.MessageBean">

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

<property name="age" value="18"></property>

<property name="birth" value="2017-05-05"></property>

</bean>

测试类:

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

MessageBean msg=ac.getBean("msg",MessageBean.class);

msg.show();

 

List集合例子:

private List<String> friends;

xml:

<property name="friends">

<list>

<value>tom</value>

<value>jack</value>

</list>

</property>

 

Set集合例子:

private Set<String> cities;

xml:

<property name="cities">

<set>

<value>北京</value>

<value>上海</value>

</set>

</property>

 

Map集合例子:

private Map<String,String> books;

xml:

<property name="books">

<map>

<entry key="1001" value="java基础"></entry>

<entry key="1002" value="python基础"></entry>

</map>

</property>

 

Properties例子:

private Properties db;

xml:

<property name="db">

<props>

<prop key="username">alex</prop>

<prop key="password">1234</prop>

</props>

</property>

 

以上所有的完整xml:

<bean id="msg" class="org.alexhe.bean.MessageBean">

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

<property name="age" value="18"></property>

<property name="birth" value="2017-05-05"></property>

<property name="friends">

<list>

<value>tom</value>

<value>jack</value>

</list>

</property>

<property name="cities">

<set>

<value>北京</value>

<value>上海</value>

</set>

</property>

<property name="books">

<map>

<entry key="1001" value="java基础"></entry>

<entry key="1002" value="python基础"></entry>

</map>

</property>

<property name="db">

<props>

<prop key="username">alex</prop>

<prop key="password">1234</prop>

</props>

</property>

</bean>


 

unit02_2

xml里bean的外部定义List ,set,map的方法(这样可以重用)

xml里的约束:

<beans  xmlns="http://www.springframework.org/schema/beans"    

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   

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

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

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

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

    xsi:schemaLocation="    

    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd

        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

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

xml:

<!-- 定义List<String>对象 -->

<util:list id="someList">

<value>java</value>

<value>python</value>

</util:list>

<!-- 定义Set<String>对象 -->

<util:list id="someSet">

<value>beijing</value>

<value>上海</value>

</util:list>

<!-- 定义Map<String,String>对象 -->

<util:map id="someMap">

<entry key="1003" value="oracle"></entry>

<entry key="1004" value="mysql"></entry>

</util:map>

<!-- 定义Properties对象 -->

<util:properties id="someProp">

<prop key="username">root</prop>

<prop key="password">pass</prop>

</util:properties>

<bean id="msg1" class="org.alexhe.bean.MessageBean">

<property name="friends" ref="someList"></property>

<property name="cities" ref="someSet"></property>

<property name="books" ref="someMap"></property>

<property name="db" ref="someProp"></property>

</bean>

 

java的src下面有个db.properties

<bean id="msg1" class="org.alexhe.bean.MessageBean">

<property name="friends" ref="someList"></property>

<property name="cities" ref="someSet"></property>

<property name="books" ref="someMap"></property>

<property name="db" ref="dbParams"></property>

</bean>

 

<!-- 读取src下的db.properties,行程Properties对象 -->

<util:properties id="dbParams" location="classpath:db.properties">

</util:properties>

 

spring表达式注入:#{表达式}   #{id名.属性}或者#{id名.key}。如果是对象属性,需要有getXXX方法。

 

<bean id="msg1" class="org.alexhe.bean.MessageBean">

<property name="friends" ref="someList"></property>

<property name="cities" ref="someSet"></property>

<property name="books" ref="someMap"></property>

<property name="db" ref="dbParams"></property>

<property name="name" value="#{dbParams.user}"></property> 如果要调用上一章springcontext里的msg的name,应该写成#{msg.name} #{someList[1]}这样取到的是python

</bean>

<!-- 读取src下的db.properties,行程Properties对象 -->

<util:properties id="dbParams" location="classpath:db.properties">

</util:properties>


 

3.利用注解配置应用IOC

在jdk5.0时追加一些新特性:

List<String> 泛型

for(String s:list)增强for循环

Integer i=10;自动装箱拆箱

注解:在类定义,方法定义,成员变量定义,前面使用,格式为@注解标记名。

public void f1(String .. s){} 动态参数

 

a。组件自动扫描

可以按指定的包路径,将包下所有组件扫描,如果发现组件类定以前有以下标记,会将组件扫描到Spring容器。

@Component

@Controller//控制层

@Service//业务层

@Repository//数据访问层Dao

@Named(需要引入第三方标准包)

 

@Scope控制对象创建

@PostConstruct指定init-method

@PreDestroy指定destroy-method

@Resource可以在变量定义前活着setXX方法前应用。按默认名称规则装配,@Resource(name="p1")按指定名字装配

@Autowired可以在变量定义前活着setXX方法前应用。按类型自动装配

@Qualifier("id名")按照名字自动装配,如果autowire有两个想同类型,可以和qualifier配合使用。

@Value("") spring表达式注入

resource和autowire在一般使用时,功能相同,都可以实现注入。如果不存在多个匹配类型,使用两者都行。

如果有多个匹配类型,建议按名称注入@Resource(name="指定名称")。

而autowire有多个匹配类型就要配合qualifier一起使用

例子:

@Component("ds")

public class MyDataSource{

  @Value("#{db.username}")//取出xml名字为db的组件,key为username

  private String username;

  @Value("#{db.password}")

  private String password;

  public void getConnection(){

    System.out.pringln("利用链接参数创建数据库连接");

  }

  //省略set方法

}

xml:

直接写<beans>里

<!-- srping创建一个properties对象,然后利用@Value表达式注入,将properties对象信息给MyDataSource注入-->

<util:properties id="db">

  <prop key="username">alex</prop>

  <prop key="password">1234</prop>

</util:properties>

 

 

请求-->DispatcherServlet-->Controller-->Service-->Dao

例子:

xml:

<!-- 开启组件扫描 扫描此包下和子包下所有组件-->

<context:component-scan base-package="org.alexhe"/>

java代码:

@Component//扫描ExampleBean组件,默认id=exampleBean,并且是单例的

public class ExampleBean {

 

public void execute(){

System.out.println("执行execute处理方法");

}

}

 

@Component("exam1")//指定id=exam1

@Scope("prototype")//等价于<bean scope="prototype"></bean>

public class ExampleBean1 {

 @PostConstruct//等价于<bean init-method="">

public void init(){

System.out.println("init方法");

}

 @PreDestroy//等价于<bean destroy-method=""> 很少用,最上面已经介绍。

public void destroy(){

System.out.println("释放资源");

}

public void execute(){

System.out.println("exampleBean1执行execute处理方法");

}

}

 

b。注入注解

方式一:使用resource注解放在变量定义前

computer类:

@Component("c")

public class Computer {

public void show(){

System.out.println("显示计算机配置信息");

}

}

Phone类:

@Component("p")

public class Phone {

public void show(){

System.out.println("显示手机配置信息");

}

}

Student类:

@Component("s")

public class Student {

//需要调用computer和phone对象

@Resource//默认按名称方式传递进来,如果找不到c对象才会按类型注入

private Computer c;

@Resource

private Phone p;

public void show(){

System.out.println("显示学生信息");

c.show();

p.show();

}

public void setC(Computer c) {

this.c = c;

}

public void setP(Phone p) {

this.p = p;

}

}

xml:

<!-- 开启组件扫描 扫描此包下和子包下所有组件-->

<context:component-scan base-package="org.alexhe"/>

测试类:

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

Student s=ac.getBean("s",Student.class);

s.show();

 

方式二:在Student类的setComputer和setPhone方法前加注解@Resource,变量前不加。

方式三:使用@Autowired注解,和方式一和方式二一样,加在变量前或者setXXX方法前。autowired默认按类型来注入。

resource和autowire的区别:resource注解用的是javax.annotation.Resource    autowired使用的是spring包里的。 resource可以有两个相同类型的组件比如两个Computer,而autowired不能有两个同类型的。

注解和xml管理的区别:注解可以没有set方法(比如Student可以没有setComputer和setPhone),但xml一定要有set方法。

autowire和qualifier配合使用的例子:

@Autowired//按类型

public void SetP(@Qualifier("anotherp") Phone p){

  this.p=p;

}

或者:

@Autowired//按类型

@Qualifier("anotherp") 

public void SetP(Phone p){

  this.p=p;

}

 

 

 

posted @ 2017-05-04 23:06  alexhe  阅读(256)  评论(0编辑  收藏  举报