Spring基础——IOC九种bean声明方式

Spring简介

Spring不是服务于开发web项目的功能,或业务。而是服务于项目的开发,方便各层间的解耦调用,方便对类的批量管理,是提高软件开发效率,降低后期维护成本的框架。

Spring的核心思想是IOC(控制反转),AOP(切面编程)两点。

IOC:即不再需要程序员去显式地New一个对象,而是把Spring框架把框架创建出的对象拿来用。因为是spring框架创建的对象,对象都在spring框架对象中保存,亦称为spring容器,这样spring就知道当前项目中都创建了哪些对象,这个对象归属于那一层,该如何管理。想使用spring的其他功能第一点就是要用spring的对象,也称为将控制权交给spring管理。

AOP:对某种路径下的所有类,或有共同特性的类或方法统一管理,在原任务执行的前后,加入新功能。做出监控,初始化,整理,销毁等一系列统一的伴随动作。

如果你从事Java编程有一段时间了, 那么你或许会发现(可能你也实际使用过) 很多框架通过强迫应用继承它们的类或实现它们的接口从而导致应用与框架绑死。这种侵入式的编程方式在早期版本的Struts以及无数其他的Java规范和框架中都能看到。Spring竭力避免因自身的API而弄乱你的应用代码。Spring不会强迫你实现Spring规范的接口或继承Spring规范的类,相反,在基于Spring构建的应用中,它的类通常没有任何痕迹表明你使用了Spring。 最坏的场景是, 一个类或许会使用Spring注解, 但它依旧是POJO。

任何一个有实际意义的应用(肯定比Hello World示例更复杂) 都会由两个或者更多的类组成, 这些类相互之间进行协作来完成特定的业务逻辑。 按照传统的做法, 每个对象负责管理与自己相互协作的对象(即它所依赖的对象) 的引用, 这将会导致高度耦合和难以测试的代码。

IOC声明Bean

首先创建的Maven Poject,详细包结构如下

其中AOP会在下一篇进行讲解;

Controller_.java

/**

    * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

    */protectedvoiddoGet(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{// TODO Auto-generated method stubresponse.getWriter().append("Served at: ").append(request.getContextPath());ClassPathXmlApplicationContext ctx=newClassPathXmlApplicationContext("/ApplicationContext.xml");Service_ s=(Service_)ctx.getBean("service_Impl1_new");System.out.println(s);s.show();}

由于Spring无法单独演示,所以Controller_.java是创建的是一个Servlet,直接调用doPost或者doGet方法,进行Service的实现,输出Service_对象s,执行show方法。

Service_.java

publicinterfaceService_{publicvoidshow();}

创建一个Service接口,用来实现Spring。

1.无参构造方法声明bean

Service_Impl1.java

publicclassService_Impl1implementsService_{publicService_Impl1(){// TODO Auto-generated constructor stubSystem.out.println("service1-无参构造方法");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl1");}}

重写Service_的show方法输出实现了Service_Impl1,编写无参构造方法。

ApplicationContext.xml

<!--默认构造方法--><bean id="service_Impl1"class="com.zy.spring.service.serviceimpl.Service_Impl1"></bean>

需要设置id与class,class对应Service_Impl1,id则是Controller_.java调用的getBean中的参数。运行结果见自定义构造方法注入bean。

2.自定义构造方法声明bean

Service_Impl2.java

publicclassService_Impl2implementsService_{publicService_Impl2(inta){// TODO Auto-generated constructor stubSystem.out.println("service2-自定义构造参数:"+a);}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl2");}}

ApplicationContext.xml

<!--自定义构造方法--><bean id="service_Impl2"class="com.zy.spring.service.serviceimpl.Service_Impl2"><constructor-arg index="0"value="1024"></constructor-arg></bean>

<constructor-arg index="0" value="1024"></constructor-arg>这是构造方法中参数的设置,index顾名思义就是索引的意思,其中a参数是第0个,value是参数的值。

3.单实例 懒加载声明bean

Service_Impl3.java

publicclassService_Impl3implementsService_{publicService_Impl3(){// TODO Auto-generated constructor stubSystem.out.println("service3-懒加载 单实例");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl3");}}

ApplicationContext.xml

<!--单实例 懒加载--><bean id="service_Impl3"class="com.zy.spring.service.serviceimpl.Service_Impl3"lazy-init="true"scope="singleton"></bean>

lazy-init=“true” 设置懒加载,也就是调用的时候才会加载bean,不会自动加载;scope=“singleton” 作用域标签,单实例也就是只创建一个实例。

4.参数引用声明bean

Service_Impl4.java

publicclassService_Impl4implementsService_{Service_ s3;publicService_getS3(){returns3;}publicvoidsetS3(Service_ s3){this.s3=s3;}publicService_Impl4(){// TODO Auto-generated constructor stubSystem.out.println("service4-参数引用bean");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl4");}}

ApplicationContext.xml

<!--参数引用bean--><bean id="service_Impl4"class="com.zy.spring.service.serviceimpl.Service_Impl4"><property name="s3"ref="service_Impl3"></property></bean>

<property name="s3" ref="service_Impl3"></property> 参数标签,name是Service_Impl4中的参数s3,ref链接要引用的bean。

5.初始化属性声明bean

Service_Impl5.java

publicclassService_Impl5implementsService_{String name;ArrayList<String>list;HashMap<String,String>map;HashSet<Integer>set;@OverridepublicinthashCode(){finalintprime=31;intresult=1;result=prime*result+((list==null)?0:list.hashCode());result=prime*result+((map==null)?0:map.hashCode());result=prime*result+((name==null)?0:name.hashCode());result=prime*result+((set==null)?0:set.hashCode());returnresult;}@Overridepublicbooleanequals(Object obj){if(this==obj)returntrue;if(obj==null)returnfalse;if(getClass()!=obj.getClass())returnfalse;Service_Impl5 other=(Service_Impl5)obj;if(list==null){if(other.list!=null)returnfalse;}elseif(!list.equals(other.list))returnfalse;if(map==null){if(other.map!=null)returnfalse;}elseif(!map.equals(other.map))returnfalse;if(name==null){if(other.name!=null)returnfalse;}elseif(!name.equals(other.name))returnfalse;if(set==null){if(other.set!=null)returnfalse;}elseif(!set.equals(other.set))returnfalse;returntrue;}@OverridepublicStringtoString(){return"Service_Impl5 [name="+name+", list="+list+", map="+map+", set="+set+"]";}publicStringgetName(){returnname;}publicvoidsetName(String name){this.name=name;}publicArrayList<String>getList(){returnlist;}publicvoidsetList(ArrayList<String>list){this.list=list;}publicHashMap<String,String>getMap(){returnmap;}publicvoidsetMap(HashMap<String,String>map){this.map=map;}publicHashSet<Integer>getSet(){returnset;}publicvoidsetSet(HashSet<Integer>set){this.set=set;}publicService_Impl5(){// TODO Auto-generated constructor stubSystem.out.println("service5-初始化属性");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl5");}}

其中初始化参数有list,map,set以及普通参数,重写了hashCode和equals方法,详见HashMap内存泄漏;重写toString方法用来输出初始化属性。

ApplicationContext.xml

<!--初始化属性--><bean id="service_Impl5"class="com.zy.spring.service.serviceimpl.Service_Impl5"><property name="name"value="zy"></property><property name="map"><map><entry key="AAA"value="aaa"></entry><entry key="BBB"value="bbb"></entry></map></property><property name="list"><list><value type="java.lang.String">QQQ</value><value type="java.lang.String">WWW</value></list></property><property name="set"><set><value type="java.lang.Integer">111</value><value type="java.lang.Integer">222</value></set></property></bean>

其中map标签内使用<entry key="AAA" value="aaa"></entry>进行赋值。其他的正常使用property和value进行赋值。

6.初始化属性引用方法返回值声明bean

Service_Impl6.java

publicclassService_Impl6implementsService_{String s5_toString;publicStringgetS5_toString(){returns5_toString;}publicvoidsetS5_toString(String s5_toString){this.s5_toString=s5_toString;}publicService_Impl6(){// TODO Auto-generated constructor stubSystem.out.println("service6-调用方法返回值");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl6 返回值"+s5_toString);}}

其中调用了Service_Impl5的toString方法并且进行了输出。

ApplicationContext.xml

<!--调用方法返回值--><bean id="service_Impl6"class="com.zy.spring.service.serviceimpl.Service_Impl6"><property name="s5_toString"><beanclass="org.springframework.beans.factory.config.MethodInvokingFactoryBean"><property name="targetObject"ref="service_Impl5"></property><property name="targetMethod"value="toString"></property></bean></property></bean>

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">固定用来声明调用方法返回值。

<property name="targetObject" ref="service_Impl5"></property> 引用目标的bean

<property name="targetMethod" value="toString"></property>引用目标的方法

7.静态工厂——声明工厂bean

Service_Impl7.java

publicclassService_Impl7implementsService_{publicstaticService_StaticFactory(intnum){switch(num){case1:returnnewService_Impl1();case2:returnnewService_Impl2(100);case3:returnnewService_Impl3();case4:returnnewService_Impl4();case5:returnnewService_Impl5();default:returnnewService_Impl6();}}publicService_Impl7(){// TODO Auto-generated constructor stubSystem.out.println("service7-静态工厂");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl7");}}

静态工厂在实现类中使用了switch语句进行模拟,静态工厂在方法前加上static关键字,分别调用上面的其他实现类方法。

ApplicationContext.xml

<!--静态工厂--><bean id="service_Impl7"class="com.zy.spring.service.serviceimpl.Service_Impl7"factory-method="StaticFactory"><constructor-arg name="num"value="2"></constructor-arg></bean>


使用构造方法注入的方法来赋值<constructor-arg name="num" value="2"></constructor-arg> ;factory-method=“StaticFactory” ( factory-method工厂的方法名)

8.实例工厂——声明工厂bean

Service_Impl8.java

publicclassService_Impl8implementsService_{publicService_factory1(intnum){switch(num){case1:returnnewService_Impl1();case2:returnnewService_Impl2(100);case3:returnnewService_Impl3();case4:returnnewService_Impl4();case5:returnnewService_Impl5();default:returnnewService_Impl6();}}publicService_Impl8(){// TODO Auto-generated constructor stubSystem.out.println("service8-实例工厂");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl8");}}

ApplicationContext.xml

<!--实例工厂--><bean id="service_Impl8"class="com.zy.spring.service.serviceimpl.Service_Impl8"></bean><bean id="service_Impl8_new"factory-bean="service_Impl8"factory-method="factory1"><constructor-arg name="num"value="2"></constructor-arg></bean>

创建实例工厂bean,首先创建一个实例工厂的bean,然后再创建一个工厂方法的bean去调用工厂的bean。

调用的时候要调用工厂方法的bean,这里就要调用service_Impl8_new

9.注解声明bean

@Service:用于标注业务层组件

@Controller:用于标注控制层组件(如struts中的action)

@Repository:用于标注数据访问组件,即DAO组件

@Component(value="*"):泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注

Service_Impl9.java

@ServicepublicclassService_Impl9implementsService_{publicService_Impl9(){// TODO Auto-generated constructor stubSystem.out.println("service9-注解注入bean");}@Overridepublicvoidshow(){// TODO Auto-generated method stubSystem.out.println("Service_Impl9");}}

@Service进行bean的声明(注解只能声明无参构造方法,使用注解默认声明的bean是类名的首字母小写),这里声明的bean的id应该是service_Impl9。

ApplicationContext.xml

<!--注解扫描IOC根目录--><context:component-scan base-package="com.zy.spring"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/><!--扫描不包括controller--></context:component-scan>


使用注解需要加上注解扫描,其中base-package是扫描的目录,一般使用的是项目的根目录,以后使用SpringMVC的话,就不用扫描Controller。

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

推荐阅读更多精彩内容