Java 18:Spring 1(装配Bean)
来源:互联网 发布:windows 2008 server 编辑:程序博客网 时间:2024/05/23 18:11
本来不想对Spring学习过程写详细的博客的,因为觉得Spring还是工程上的东西,实践大于理论,况且各种配置什么比较繁琐,这一写,没个七八篇下不来。但是学习了《Spring实战》以后比较烦,感觉这本书并不那么好,其他就不说了,上面好些代码有问题就不能忍了,作者从理论介绍的角度还可以,但是从初学者接地气的方面,就不太好了。例子比较复杂、抽象,代码大小写问题屡见不鲜,不少代码运行不了,大量用了JUnit,我又不会那个。然后三种配置方式交替说明,虽然全面,但是也容易混乱,所以,还是一步一步地从头学起,不能光依赖这本书了。后文主要还是顺着《Spring实战》的顺序学习,但很多具体实现是网上的博客的例子。
-----------------------------------------------------------------------------------------------------------------------------------------
Spring诞生之初,主要是代替更加重量级的企业级Java技术,尤其是EJB,它增强了“简单老式Java对象”POJO的功能,使其具备了之前只有EJB和其他企业级Java规范才有的功能。
EJB:Enterprise Java Beans(EJB)称为Java 企业Bean,是sun的JavaEE服务器端组建模型。设计目标与核心应用是部署分布式应用程序。EJB相比现在的框架,更加重量级,更加繁琐,用的人已经比较少。
POJO:普通的Java bean,是为了避免和EJB混淆创造的简称。具有一部分getter/setter方法的类就可以称作POJO
Java Bean:比POJO复杂,Java Bean是可重用的平台独立的软件组件,没有严格的规范,但通常情况下,由于Java Bean是被容器(比如Tomcat)所创建的,因此应该具有无参的构造器。另外,一般还需要实现Serialzable接口用于实现Bean的持久性。还有人说,提供getter、setter也是要求之一。
Java Bean主要用来存储状态信息,EJB则可以存储业务逻辑。
总之,Spring是为了解决企业级应用开发的复杂性而创建的,使用Spring可以让简单的Java Bean实现之前只有EJB能完成的事。虽然Spring用Bean来表示组件,但是并不需要遵循 Java Bean规范,一个Spring组件可以是任何形式的POJO。为了降低Java开发的复杂性,Spring采取以下几种策略:
1、基于POJO的轻量级、最小侵入的编程
2、依赖注入、面向接口实现松耦合
3、基于切面和惯例进行声明式编程
3、基于切面和模板减少样板式代码
1、依赖注入:
Spring极力避免自身的API弄乱你的应用代码,许多框架要求继承它们的类或接口,而导致应用于框架绑死,比如EJB2时期的无状态会话Bean。居于Spring构建应用,通常没有任何痕迹说明你使用了Spring,即使使用了Spring注解,它依然是一个POJO。
按照传统的做法,每个对象管理自己依赖的对象,这将导致高度耦合和难以测试的代码。而通过依赖注入,对象之间的依赖关系将由第三方管理。
//传统依赖关系public class Knight{private RescueDamseQuest quest;public Knight(){this.quest=new RescueDamseQuest();//生命周期由自己创建管理,且限定到具体的实现类}public void embackQuest(){quest.embark();}}
//采用构造器注入方式public class Knight{private Quest quest;//不用声明为具体实现类,只需要给一个接口,使得Knight能响应任意实现public Knight(Quest quest){this.quest=quest;//自动注入进来,不需要显式声明}public void embackQuest(){quest.embark();}}
依赖注入的最大好处就是松耦合,创建组件之间协作行为成为“装配”,最普遍的就是将之用XML表示。2、应用切面
面向切面编程AOP,允许把遍布应用各处的功能分离出来形成可重用的组件。诸如日志、安全、事务管理这些系统服务经常要融入到其他业务组件中,这些系统服务称为横切关注点,因为它们横跨多个系统。
关注点分散到多个组件中,带来了复杂性,出现重复代码,使自身代码混乱。AOP能够使这些服务模块化。并以声明式的方式将它们应用到需要的组件中,结果就是这些组件会有更高的内聚性,更加专注于自身的业务。
3、使用模板消除样本模板
类似于JDBC,真正查询数据库的代码可能只有一两行,其他都是重复的操作,Spring的JabcTemplate可以让你关注核心业务,免去大量的模板代码
在Spring中,应用对象存在于Spring容器中,Spring负责创建对象、装配它们,配置并管理它们的整个生命周期,从new到死亡。容器是Spring框架的核心,Spring容器使用DI(依赖注入)管理组件。Spring有多种容器实现:bean工厂、和基于Bean工厂构建的“应用上下文”。应用上下文比Bean factory更加高级,也是我们主要用到的地方。
常见的应用的上下文:
AnnotationConfigApplicationContext:从Java配置类加载Spring应用的上下文
AnnotationConfigWebApplicationContext:从Java配置类加载Spring Web应用的上下文
ClassPathXmlApplicationContext:从类路径下的XML文件加载上下文
FileSystemXmlApplicationContext:从文件系统下的XML加载上下文
XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文
首先,这些名字比较复杂,但是《Spring实战》几行里出现了多处大小写问题让我很不爽(难道买到了假的书?)。可以看出,主要是XML和Java配置类两种方式进行上下文的配置。对于配置文件的路径、读取方式,书里面好多也没写清楚,包括网上的很多例子,这是前期敲代码给我造成很多困扰的地方。
Bean的生命周期:
比较复杂,可能也比较重要,但现在看不懂,步骤太多,先留着。
一、装配Bean:
Spring3种装配:1、XML 2、Java显式装配 3、隐式的Bean发现机制和自动装配。 3种方式可以混合使用,也有一些不同的应用场景,比如使用第三方Bean的时候,就没法使用注解来自动装配。
建立一个叫beans.xml的文件来说明Bean之间的依赖关系,前面提到的几种上下文中,有基于Web和不基于Web之分。我们知道Web中有WEF-INF、Web.xml等固有的文件和文件夹,这也是让我比较混乱的地方,不知道各种配置文件的路径怎么表示,这里先从啥都没有的普通Java项目开始,这里的代码主要来自:http://blog.csdn.net/heyutao007/article/details/5981555,很通俗易懂,感谢,Java配置部分的配置则来源于于书上的例子(《Spring实战》最喜欢Java配置方式了)。
(1)XML装配Bean:
Boss.java
package com.baobaotao;public class Boss {private Car car;private Office office; //以及两个字段对应的set、get方法,这种xml基本配置情况下,任意一个Bean没有两个方法会创建Bean失败public String toString(){return "car:"+car+" office:"+office;}//输出用,并非必须}
Car.java
package com.baobaotao;public class Car {private String brand;private Double price;//同样的篇幅原因,省略get、set,自己要补上public String toString(){return brand+" "+price;}}
Office.javapackage com.baobaotao;public class Office {private String officeNo;public String toString(){return officeNo;}//get、set}
beans.xml:后面使用的是ClassPathXmlApplicationContext,意味着默认路径是类路径,也就是src目录下,和package同路径<?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.xsd"> <bean id="boss" class="com.baobaotao.Boss"> <property name="car" ref="car"/> <property name="office" ref="office"/> </bean> <bean id="office" class="com.baobaotao.Office"> <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean> </beans>
这里的注意点,也只是beans后面的引用不要打错或者缺少。offfice、car设置了初值。注意三个Bean我们都没有显式设置任何构造函数和设置域
如果,我们想要借助构造函数来设置Bean,就需要在java类里显式声明构造函数,比如Car(String,Double),然后XML就以构造函数方式填写参数,用<constructor-arg>而不是<property>(spring3引入的c-命名空间可以代替constructor,但我最讨厌这些标签表达式了):
<bean id="car" class="com.baobaotao.Car" scope="singleton">
<constructor-arg value=" 红旗 CA72"/>
<constructor-arg value="2000"/>
</bean>
最后的效果是一样的。注意:构造器注入需要对应的构造函数,property属性设置则需要对应的getter、setter方法
main函数:
public static void main(String[] args) { String[] locations = {"beans.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(locations); //这种上下文的基本路径就是类路径,src下 Boss boss =ctx.getBean(Boss.class); Boss boss2 =(Boss) ctx.getBean("boss"); //根据id和类名都可以从上下文得到实例,但是根据id需要进行类型强转 System.out.println(boss2); }
自动装配:Autowired
beans.xml: <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> //增加使用注解的功能 <bean id="boss" class="com.baobaotao.Boss"/> //介绍对两个property的声明
Boss.java: 只修改了Boss类,而Car和Office还不会用注解进行设置,不做改变public class Boss {@Autowiredprivate Car car;@Autowiredprivate Office office;public String toString(){return "car:"+car+" office:"+office;}}
使用@Autowired进行域的自动装配,并且可以省略getter和setter的声明。另一种对“构造函数”的自动装配,效果也是一样
public class Boss {private Car car;private Office office;@Autowiredpublic Boss(Car car,Office office){this.car=car;this.office=office;}public String toString(){return "car:"+car+" office:"+office;}}
最后一种针对setter的自动装配:public class Boss {private Car car;private Office office;@Autowiredpublic void setCar(Car car) {this.car = car;}@Autowiredpublic void setOffice(Office office) {this.office = office;}public String toString(){return "car:"+car+" office:"+office;}}
以上三种情况,最终的效果是一样的。(2)、XML组件扫描:
不仅希望将依赖关系通过注解来实现,也能通过组件扫描,让Bean也不需要显式在XML里声明:
beans.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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"> //有了几个新增的,一定要写对,不然会报错 <context:component-scan base-package="com.baobaotao" /> //对baobaotao进行组件扫描,不用再显式声明Boss <bean id="office" class="com.baobaotao.Office"> //依赖的这些类,不会自动装配设置初值,先留着(上面用于注解的一句话也不需要了) <property name="officeNo" value="001"/> </bean> <bean id="car" class="com.baobaotao.Car" scope="singleton"> <property name="brand" value=" 红旗 CA72"/> <property name="price" value="2000"/> </bean> </beans>
Boss.java@Component //Component代表扫描时,当成Bean,也就是实现了组件自动扫描的功能public class Boss {@Autowiredprivate Car car;@Autowiredprivate Office office;public String toString(){return "car:"+car+" office:"+office;}}
(3)Java配置类实现组件扫描+自动装配
BossConfig.java:
@Configuration@ComponentScan //功能和xml里的组件扫描一样public class BossConfig {}
Boss.java、Car.java、Office.java:@Componentpublic class Boss {@Autowiredprivate Car car;@Autowiredprivate Office office;public String toString(){return "car:"+car+" office:"+office;}}
@Componentpublic class Car {private String brand="brand";private Double price=(double) 2000;public String toString(){return brand+" "+price;}}
@Componentpublic class Office {private String officeNo="no";public String toString(){return officeNo;}}
main方法: ApplicationContext ctx =new AnnotationConfigApplicationContext(BossConfig.class); //换成相应的上下文 Boss boss =(Boss) ctx.getBean(Boss.class); System.out.println(boss);
(4)纯Java代码装配Bean
用Java代码装配Bean的作用我感觉和XML基本一样,只是把XML的功能移到一个Java Config类里,那和前面的自动装配有什么不同?只能说,Java Config更加显式一点,每一个Bean都是明明白白的设置的(虽然感觉@Component也够明显的了),并且所有的Bean是集中放置,这就和XML更接近了,当然由于Java允许多种装配方式混用,所以用着用着就搞不清它们之间的界限了。
CDplayer.java: 没有什么额外的东西,就是一个普通的POJO
public class CDplayer {private Cd cdprivate;public CDplayer(Cd cd) {this.cdprivate=cd;}public String toString(){return "player:"+cdprivate.name;}}Cd.java :依赖的另一个Bean
public class Cd {public String name;public Cd(String name){this.name=name;}}Config.java :证明Bean的配置类,和前面组件扫描的配置类的区别是1、多了每个Bean的专门声明 2、少了ComponentScan设置
@Configurationpublic class Config {@Beanpublic CDplayer cdplayer(Cd cd){return new CDplayer(cd);}@Beanpublic Cd cd(){return new Cd("as");}}有了前面的基础,相信这些代码都不难懂,@Bean注解表明了CDplayer和Cd都变成了Bean,需要注意的是,这里Bean的名字可以显式声明,否则会以函数名作为名字,也就是cdplayer和cd。
最后的测试也和前面一样:
main函数:
public static void main(String[] args) {// TODO Auto-generated method stub ApplicationContext ctx =new AnnotationConfigApplicationContext(Config.class); CDplayer boss = ctx.getBean(CDplayer.class); System.out.println(boss); }
- Java 18:Spring 1(装配Bean)
- Spring装配Bean——Java代码装配bean
- spring笔记1 装配bean
- Spring(二)--Bean装配
- Spring(4)装配Bean
- Spring实战(装配Bean)
- Spring(一)装配Bean
- Spring(二)---装配Bean
- Spring学习(七):通过Java代码装配bean
- java spring Bean Autowiring 自动依赖装配
- 通过Java代码装配bean【Spring 入门】
- Spring 如何通过 Java 代码装配 bean?
- Spring Bean装配-自动装配
- Spring(1-1、基于xml装配Bean)
- 《Spring In Action》 读书笔记(1) -- bean装配
- Spring(1-2、基于xml装配Bean)
- spring之如何创建bean(1、自动装配)
- spring入门(8)--装配Bean之自动装配
- 【dfs】poj 1020 Anniversary Cake
- 矩阵分析与应用(四)——逆矩阵、广义逆矩阵和Moore-Penrose逆矩阵
- Java设计模式:工厂方法模式(Factory Method Pattern)
- 一个想法照进现实-《IT连》创业项目:一个转折一个反思
- xml读取辅助类
- Java 18:Spring 1(装配Bean)
- struts2标签<s:property value=""/> ognl和el
- PHP+mysql 入门级通讯录(四)
- js04.if...else条件判断
- 简明 VIM 练级攻略
- 时间帮助类
- hdu 1754 I Hate It
- ipcs ipcrm
- rom和ram的区别