学编程重要的是记忆?还是思考?在底层逻辑很抽象的概念中,思考的方向怎么理论联系实际?

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

预制菜产业正在预见一个历史性变革的诞生。

看似平常的一批加工菜品背后,是一个深不可测的商业海洋。

作为预制菜策源地的广东,正在引领风气之先——成立省级联席会议制度,出台省“菜十条”,创建11个省级预制菜产业园,成立省级预制菜产业联合研究院,设立预制菜产业发展投资基金……不仅如此,7月中在佛山市顺德区举办预制菜院士论坛,十大院士为预制菜的质量、安全、营养等发展方向把关,为制度、标准、人才的提升出谋划策,受到国内业界高度关注。

近日,受广东省农业农村厅邀请,著名经济学家、北京大学国家发展研究院周其仁教授走进预制菜策源地广东,深入佛山、肇庆、广州南沙、海珠等地企业调研,与政府及企业代表面对面。在预制菜产业如火如荼之时,为预制菜全产业链把脉,分析要害、抓住规律、框定机理、升华经验。

在广东预制菜产业高质量发展调研座谈会上,广东省农业农村厅分管负责人在主持会议时表示:在行业“热发展”之时,尤其需要“冷观察”“冷思考”,务必客观理性、冷静淡定。

要避免一哄而上,行业踩踏;

要避免泥沙俱下,坏了好“汤”;

要避免链条短缺,联动失灵;

要避免急功近利,后继无力。

要把质量安全作为底线,夯实发展底座;

要把市场挺在前沿,以需求引领生产;

要不忘联农带农初心,以乡村振兴作为出发点;

要科学谋划,不急不燥,步履扎实,一步一个脚印,行稳致远。

盛夏之际,大热之时,周其仁教授基于“冷观察”、“冷思考”,走进预制菜产业,访企业,走市场,与企业家面对面,深入交流、细致调研。以下是调研交流记录。内容未经本人审阅。

口述:周其仁  北京大学国家发展研究院经济学教授

千军万马冲进来,一个产业迅速从蓝海杀成红海

产业火不等于公司火,要准备打硬仗 

各界推动产业发展的好处,是产业规模可迅速扩大。但代价是,预制菜本身行业壁垒不高,窗户一点破,千军万马冲进来,挡都挡不住。一哄而上,良莠不齐,有时候甚至劣币驱逐良币。一个产业迅速从蓝海杀成红海,企业从有希望做成没希望。

中国市场是天底下最容易把蓝海变成红海的地方。曾经我们因为计划经济物资短缺,都是从生产角度去研究,就形成了这种惯性。只要有需求,都能迅速生产制造出来。这也导致中国这些年经济的特点,是高速增长却损耗极大。

我相信没有企业喜欢红海,但是谁也摆脱不了迅速成为红海的现实。所以现在就要开始预防,准备打硬仗,如果未来蓝海变成了红海,我们能否从红海里再杀出一片蓝海,留下一批好公司。

产业火不等于公司火。政府和投资者的行为很难改变,但企业要掌握策略。预制菜的大概念对了,不等于产品就对了。要借新概念把企业的核心竞争力加强,把核心技能延伸到这个新概念里头去。而不要认为有了预制菜这个概念,产业就可以自动发展。

千万要注意,在好时期企业就要把品质的壁垒竖起来。品类是公共的,依靠预制菜这个品类来保护企业靠不住,还是要靠你自己拥有好的产品。 消费者看的是产品,不是产业。不能说因为是预制菜,所以就比外卖好,消费者就一定就会买。

要研究消费行为,建立客户链

聚焦用户,攻占消费者心智结构

 什么人在吃预制菜?

不管是To B还是To C,最终所有生意都是做C端的生意。要紧紧抓住对预制菜敏感的消费群体,深入研究并理解其消费行为。在产业发展早期,尽可能多地捕捉到能够帮助判断未来趋势的信息。

对客户的研究程度要超过你的竞争对手。企业除了在技术、管理、研发等方面投入,还要有很大一部分精力来研究消费者。特别是对年轻消费群体的研究,第一步要熟悉、适应其消费习惯和消费行为;第二步要融入其中;第三步才是逐渐改变其消费行为,达到教育消费者的目的。

我们到世界美食之都——佛山顺德的品珍鲜活调研,两姐弟做预制菜很花心思。他们说自己的定位就是服务于20-50岁年龄段的消费者。目前,很多企业都是从生产、技术、管理等方面想问题,当然这些是必要条件,但还要在消费习惯、消费心智、消费行为上下硬功夫。企业能掌握到最终消费者,掌握什么东西卖给谁,什么东西能卖得好,这才是最高的本事。

另外,企业不要急于进军,要先占领消费者的心智结构。企业往往存在一个问题,就是自己看自己很清晰,但其实消费者看不见你。专业术语叫心智结构里装不下你。

比如有在饭店里卖铁盒包装,撕开加热的罐头,被消费者吐槽,认为“在门店里还吃罐头”。所以企业就要好好考虑,在门店吃罐头和在家吃罐头是否存在不同?如果有附加价值,那也是可为的。罐头可以有,但要考虑加什么、怎么组合,消费者才能接受,觉得对自己有价值,这是难点。

你的产品装不进消费者的心智结构,所有投入都存在很大风险,讲无数的细节指标都没用,消费者听了也记不住。

再者,消费者的记忆是可以延伸的。广州酒家的经验值得好好研究。为什么有消费者会认为广州酒家的饭好吃,月饼也好吃,其中的联想是怎么建立的?因为广州酒家这类信息储存量已经在消费者的心智结构里了。

同样道理,如果顺峰饮食卖得便宜,人们就会怀疑这还是顺峰的饮食吗?所以像这类企业,还是要坚守定位,不能因为要走大众路线,就大卖便宜货。你的好东西、贵东西还是得往消费者心里装,急于开拓新市场,就会分散消费者的注意力。

预制菜产业,目前正在建立供应链,下一步就要建立起客户链。

商业就是一个链条一个链条组合在一起的生态链。在商业上想问题,最难的就是从客户角度出发。消费者不是美食家也不是专家,他们就是普通人。所有产品到最后都是卖给消费者,没有人买单就是浪费。要研究客户的心智结构和消费习惯,以及怎么吸收信息,还有消费者之间的影响链条。

所以,要从日常生活当中去捕捉消费潮流和消费习惯的变动。要记住符合客户需求和习惯的才是好产品。

此外,建议企业在做预制菜时,如果消费者对你的第一印象还没有建立,一定要考虑专精特新,专注于细分领域的特定产品。

怎么才能吸引客户买单?

一方面要靠产品的营养成分等这类客观物理特性,另一方面就是主观指标,如消费者的记忆、产品色彩、产品与某些故事的连接、情感文化价值等。这些都可以构成抓住消费者的力量,客观和主观两个维度加在一起才具有致命吸引力。

聚焦好产品,构筑护城河

难就是护城河。难,别人就杀不进来。

在调研中,企业说现在挺难的,怎么办?但其实,难就是护城河。难,别人就杀不进来。

企业要在目标客户、潜在客户这里下功夫,通过对产品的提升完善来建立起自己的“护城河”。在这些问题上抓得越细,你的护城河就越深,别人就越难进来。

预制菜企业产品要足够出众,没有特色很容易被赶超。消费者花钱购买的是产品体验,追求的是在时间、金钱等约束下的最大享受。

怎样能让消费者获得最大享受?要从产品本身入手。广东中厨食品的负责人比较明白这一点。他认为产品力+商业模式,是决定一个预制菜企业和品牌能否生存和发展的关键。我比较认同这一点。产品力就是产品的风味、口味、质量、安全,甚至包装设计等。例如肇庆的振业水产,把碗、料包、植物油灯、筷子、湿巾等这些附加物都放到了烤鱼的包装里面,这就是对产品的一个小创新。

创新的同时,还要注重保护。现在有不少仿制品以假乱真,于是就出现了一种测基因技术来进行真假鉴定,在产品中加一两种很特定的元素以防伪。

未来,预制菜大规模发展,可能会让消费者分不清真假产品,这也可能导致预制菜整个行业的信誉下降。假产品对行业未来造成的损失不可估量,因此要重视品牌和创新保护。

为了避免企业在产品创新研发过程中出现技术难题,企业要掌握先进技术,也就是拥有技术可得性。所谓的高科技都是高分工,搞不懂的细节就要自己想办法,由近而远地下功夫。正如先和学生打交道,通过学生认识学生的老师,再通过老师接触老师的老师......一层一层向上讨教,触摸到行业的技术制高点,千万不能好高骛远。越聚焦前沿,就越能打开思路,视野也会不一样。

例如调研企业中的肇庆伦太太,在做龟苓膏预制菜。龟苓膏这种传统街边小吃,要想升级为现代化规模化工业化产品,传统配方和现代科技缺一不可。配方是产品的护城河,但是中国传统里面还有很多当年无法突破的技术短板,那就需要用现在的制造技术和科学知识补齐。

当然,创新也要守旧。在追求创新的同时,也要研究耐用耐看、经久不衰的产品。例如可口可乐、香奈儿5号,100多年品牌效应深入人心。为什么有的产品能成为经典,大小、颜色、款式、配方都不变,而有的所谓“爆款”仅仅几年就消声匿迹,要好好领悟这里面的道理。

在房间里推逻辑是推不出来的,一定要研究策略、研究办法、研究经验。尤其是要好好研究广东的经验,观察别人怎么“游”。

我很欣赏英语里面有一句话——“Don’t teach fish to swim ”,不要去教鱼游泳,但是可以去观察鱼怎么游泳,去比较鱼和鱼之间游泳有什么不同。做企业也是这样,多观察别人是怎样“无心插柳柳成荫”的,多个角度学习别人的优秀经验,从中得到启发,寻求帮助,进行提炼总结,再回头把自己的事做好。

关注复购率,找准发力点

寻找“第三只口”,组成“航空母舰”

未来如果想从红海中杀出一片蓝海,企业就要提高持续性,走健康持久之路。一方面要在产品还原度上下功夫,研究食品怎么吃才能不腻;另外一方面要重视复购率。衡量一个产品的市场规模,不仅是有多少人去买,更重要的是回购的频次。

妈妈做的菜,可能并没有多么好吃,但总是念念不忘,这是因为从小吃起,先入为主。那么企业也可以借鉴这个思路,研究怎么样抓住客户的心,有复购率,这很关键。

预制菜其实以前就有,但现在概念开始集中,内涵也丰富了,并且逐步产业化。每一个产业的兴起都会涌入大量的竞争者,分工链条一旦拉长,进入的公司越多,就越容易形成内卷。

我们在调研时发现,有些企业一二三产都想布局,形成多个攻击点。但这样反而分散了精力,不如集中兵力先建立第一个支点。这个支点越可靠,你将来支撑的东西会越多。企业能把一件事干好,干得非常好,人家就有理由相信你。

所以要先创造一个支点,评估公司的特质能否先把这个事情做好。

找到支点以后,下一步就是持续发挥优势,扩大风口。一个简单的订单,浓缩着整个商业后端。每一个长项领域的积累都来之不易,与其分散发力,形成多个攻击点,不如坚定一个产业、一条道路,积累本事。然后一脚一脚往里伸,用支点撬动整个市场。

食品行业有时会面临一种现象,真东西斗不过假东西,好东西斗不过坏东西。要让消费者相信企业生产出来的是好东西,比企业生产好东西本身还难。

品牌的品,有三个口组成。厂家说产品好,这是第一只口;消费者购买产品以后的口口相传,这是第二只口;完全不相干的人说好,这是第三只口也是最难突破的一只口。

第三只口也叫“意见领袖”。企业要想让消费者相信你的产品是真东西、好东西,可以适当寻求第三只口的帮助。先研究目标客户受谁影响,再找准目标,影响那些能影响目标客户的人。第三只口的影响力越大,企业就越能成功。

预制菜市场存在各种各样的风险,这需要企业组建生产商、客户和品牌之间强有力的产业联盟。它会形成像“航空母舰”般的团队,去抵抗风险,增加产业发展的可靠性,而不至于一有风吹草动就被吹散。这是行业的生态问题,不是单个工厂,也不是单个产业,是若干主体之间的连接。

做“隐形冠军” 深藏“功与名”

有时候“笨”一点,会走得长久一点

我们在肇庆得宝调研时了解到,这家公司与客户之间存在明显分工。得宝在背后为客户生产并提供产品,客户面向消费者打出自己的品牌,跟生产制造商无关。包括像广州绿城也是,为一些知名餐饮机构做半成品加工,不做渠道的事,只做专业制造,不同企业之间组成一个链条来做生意,这是很好的经营策略。像这类生产预制食品的企业,就像“隐形冠军”,隐藏在幕后“深藏功与名”。

在调研中,我们发现有些“隐形冠军”未来具有截然不同的战略规划。有一些说他们将继续专注于生产供应端,专业的人就一直做专业的事;另外一些则蠢蠢欲动,打算兼顾B端与C端,想要冲向一个全新的领域。

隐形冠军的企业发展之路怎么走?如果从幕后到前台,如何把握?其必要性有多大?

“隐形冠军”要走到前台,是非常具有挑战性的一步。但是否要下这个决心,要根据每个企业自身的资质和战略需求。我认为要入局不一定要直接to C,专心做好B端的“隐形英雄”也可以做好预制菜。

有人认为,餐饮业的B端和C端差异非常大,两者的对象不同,同时做B端供应和C端销售并不会对现有的市场格局造成影响。但其实这个逻辑是错误的,原本专业做B端的企业转向C端市场,就是迈入和原来C端企业竞争生意的行列里去了。C端会认为这是在抢夺他的客户、他的地盘。他会不会继续全心全意依靠你,还是换一个供应商?因为他担心未来会被现在的供应商挤出局。

此外,有些人觉得企业转型扩张可以提升利润。要注意,利润可以分为两个概念,一个是利润率,一个是利润量。

举个例子,专业做代工厂的富士康利润率不高,但是其利润量非常大。这两个概念要进行区分,在企业扩张前做好战略规划才能笑到最后。富士康一直隐形在幕后,也做到相当大的规模。

天下的事情都是有两面性的,有机遇就有风险。所以企业在扩张、转型时要想清楚,有时是不能动“凡心”的,反而死心眼才能把事情做到极致。想清楚了再开这一枪,不要还没有做好规划、都没准备好就开枪,反而令自己落入进退维谷的境地,两头不是人。

有时候“笨”一点,会走得长久一点另外,B端和C端的面向对象、管理模式、经营理念都完全不同,其中的管理跨度是非常大的。如果专业做B端的企业要直接杀到C端,将面临另外一套经营模式,其中蕴藏着巨大的挑战。

当然,这条路不是完全不可行,认真研究战略发展规划,也有杀出红海的可能性。

聚焦市场,外销内销都要赢

做最好的东西,一定要在最大的市场里下手

我们在调研时也了解到,很多企业都看中了预制菜这个新商机,想要入局。但要怎样迅速抢占局面,形成大批量的市场,这里面既有投资问题也有技术问题。

阿里有一个犀牛工厂,可以把一个单子迅速变成大批量供货,7天内形成千万级别的供应能力。企业要好好思考,我们是否也可以?

中国市场很大,一个新产品开发有可能是自己的,但收益是别人的。企业必须要具备迅速形成大规模制造和供货的能力,在全国乃至全世界范围内铺设网点。

真要做最好的东西,一定要在最大的市场里下手,在足够大的市场寻找客户。把规模经济发挥到极致,这是今天工业制造的定律。

工业革命之后,工厂技术普及,人们学会了大批量制造。在过去把同样东西做成大批量是不可能的,但现在工厂技术可以做到。前期是要有市场,不然再有本事也做不下去。工厂技术、大规模制造技术是行业发展的支撑条件,所以不管是做贸易起家还是做平台起家,一定要研究这些。

而且食品工厂是很特别的工厂。有冷链,还要冻结复原味道、口感不能变差等,其中有很多技术能力。企业学会这些技术实现批量规模生产。这样一个大厦系统,要应用到预制菜领域中。

但是要注意,如果原材料不够量就不做。原材料不够,会导致学习的人有时间来追,而自己没有时间领跑。食材规模实际上是一个潜在变量,在哪采购,在哪研发,在哪生产。海底捞和西贝为什么能做好?因为他们的基本食材是羊肉,而中国北方有很多大草原,食材资源丰富,品质也比较整齐,所以在原材料供应上有保证。

好产品应为人类造。内销市场要做规模化,外销市场同样要走出去。今年国内的营商环境和消费环境都不是很好,但是海外市场不错,那么企业就要抓住机遇,短期内可以延缓在国内开展业务,适当转向海外,把实力做到一定程度,等到具备短时间内强大供货能力的时候,再选择最佳战机,进军国内市场。

怎么选择合适的海外市场?以东盟国家为例,因为跟欧洲融合得早,这些国家的消费习惯和生活素质在某些方面很超前。虽然基本不在家里吃饭,但非常重视厨房卫生和整洁。每个国家的消费习惯不一样,因此国内预制菜想要走出去,一定要想清楚到底做哪一个市场或者要出口哪一个国家。

我了解到广东海润正在韩国、日本、澳洲等一些海外地区设厂,这是一个思路。另外就是可以从华侨发力,现在很多企业做华人生意、做出国旅行人的生意,有些做得比较成功。

过去我们总有一个刻板印象:中国人中国胃,只有中国人爱吃中餐。但事实证明,中餐已经打入了外国人的心智结构。所以不要因为我是中餐,是中国企业,就只紧盯着中国市场,其实中国人也完全可以做全球市场。经济思路要打开,视野要长远。

中国企业想做海外生意,是有成本优势的。因为我们“后发”,产品物美价廉。但尽管这个生意很好做,很成熟,很容易上手,也很容易高速发展,但一旦过了拐点后就不可持续,容易产生逆差。

这时候出口企业就要面临产业转型,重新布局。我们去肇庆中业水产调研,这类企业有一个杀手锏,过去出口发达国家的产品,在质量和品控方面比国内更胜一筹,能够很好地契合国内消费升级的要求。如果能用技术升级补齐短板,未来想必大有可为。

重视金字塔底层消费市场 高端产品也要有亲和力

用预制菜承载传统文化走出去

人类发展规律是富裕起来以后,文化占比权重越来越高。美国的产业做成世界第一大经济体,它有一个长处,就是把给贵族的东西做成普通人能享受。

企业要学一个本事,就是怎样把好的东西,让越来越多的人能享受到。只有让更多人有了好的享受,他们才会有动力去好好做事;只有让更多人得到高端享受,才会激励他们创造更高端的享受给别人,这是其中一个规律。

所以高端产品从现代意义上来看,它应该有更丰富的内容。让越来越多的消费者了解并能够品尝。如非遗,不光中国人说它好,外国人也心向往之,这就是文化的厉害之处。

预制菜能否与中国传统文化相结合?以调研的广州拾三食品生产的燕窝为例,燕窝并不是中国的东西,是国外的,但是里面有一种汤文化,很契合中国文化内敛不张扬的特点。那么是否可以用汤承载更多的中国传统文化走出去?例如汤可以变成世界汤,可以不仅是一道正式菜,也可以变成餐后甜品,再加以改造变成饮料,跟现在的生活节奏相匹配,这种可能性或许也完全可以具备。

文明的最后是互相借鉴和融合,且一定要跟当代生活有某种融合,才容易被别的文明理解,才容易传承。

现在很多年轻人喜欢喝奶茶,一些奶茶店的队伍排到半夜。那么能否尝试把各种各样的羹与这些现代元素融合?让已有品类从年轻人感兴趣的角度切入。

时代不同,人的消费观念也就随之不同。新一代年轻人接收的信息具有全球化特征,会形成一套独立的思维方式。所以要从新角度出发,探索文化与当下高质量产品的融合,让预制菜以亲和力迈向更广阔的市场。

要反向作业 要防范风险

要统筹引导,热的时候要冷一点

现在预制菜产业正在大张旗鼓地发展,地方政府一定要好好观察市场,反向作业,冷的时候热一点,热的时候要冷一点。市场缺什么,才去补充什么。否则,潮水一退,就会造成资源的浪费。

政府引导方向没错,但不要让方向束缚了自己和企业的手脚。政府发一个号召,底下会有很多企业搭便车。搭便车到底是好是坏?要辩证地分析。

很多事情不是发规划和文件就能够做出来,比如珠三角怎么会冒出这么多制造业,并没有人规划。要多学习别人是怎样“无心插柳柳成荫”的。换句话说,想教别人游泳,就得先准备足够的水,否则就算人家会游泳也没办法游。相反,你把水引下去了,会游的自然就会游,改革的步子也就能走起来。

地方政府一定要发挥好统筹作用。每个预制菜产业园、每个地市、每家企业现在都要发展预制菜,但要有规划,不能拍脑袋就上,要形成广东预制菜总体的规划与布局。

比如我们调研时,有企业建议大家分工合作,每个地方做好专精特新的东西,是有道理的。预制菜相关主体确实要各取所长、差异化发展。否则,大家一窝蜂上,同质化竞争,就基本赚不到钱了,基本打成平手,这符合经济学现象,充分竞争下利润为0,都是热闹。

此外,也要留心防范未来风险。作为食品产业,食品安全一定要引起高度重视,尤其要发挥好监管部门的作用。现在宣传得有多热,反过来出问题时风险就会有多大。一旦出问题,舆论可不会冷静地去做科学分析,到时辛辛苦苦发展起来的产业就容易被抹杀。


【口述周其仁  北京大学国家发展研究院经济学教授

【来源】南方报业传媒集团南方农村报

  1. Spring主要是思想的学习,核心思想是IOC和AOP

    • 控制是指将所有的类托管给Spring创建管理控制
    • 反转是指通过属性依赖注入(DI)的方式,给对象的属性赋值,包括基本属性和引用属性(将对对象的控制权剥离处理)
    • 本质是装饰者模式和动态代理模式
    • 通过横切的方式在原有的业务代码中添加公共功能,而不改变原有业务代码





  • Spring是一个开源免费的框架,容器
  • Spring是一个轻量级的框架,非侵入式的
  • 核心特点:控制反转IOC,面向切面AOP
  • 对事务支持,对框架整合的支持

一句话概括:Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器(框架)

Spring框架是一个分层架构,由7个定义良好的模块组成。

Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式。

组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

  • **核心容器:**核心容器提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性规范与世纪的应用程序代码分开。

  • **Spring上下文:**Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。

  • **Spring AOP:**通过配置管理特性,Spring AOP模块直接将面向切面的编程功能,继承到了Spring框架中。所以,很容易地使Spring框架管理任何支持AOP的对象。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。

  • **Spring DAO:**JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误信息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构。

  • **Spring Web模块:**Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  • **Spring MVC框架:**MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。

  • 一个快速开发的脚手架;
  • 基于Spring Boot可以快速开发单个微服务;
  • 使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置;
  • Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;

Spring弊端:发展了太久之后,违背了原来的理念!配置十分的繁琐,人称:“配置地狱!”

新建一个空白的maven项目

1.原来的MVC方式写一段代码

2.dao层增加接口,产生问题

紧接着我们想要使用MySql的话,我们就需要去service实现类中修改对应的实现

要想使用Oracle,也需要在service实现类中修改对应的new对象实现

  • 如果我们有大量的类似的需求,dao层一个接口有许多实现类,用户访问就需要修改程序(service层引用的dao层实现类)

  • 每次变动都需要修改大量的代码,这种设计的耦合性太高了,牵一发而动全身

我们可以在service层中用到dao层的地方不去实现它,而是留一个接口,利用set。我们去代码里修改下:

**区别:**已经发生了根本性的变化

  • 之前程序主动创建对象,控制权在程序员手上(如service层引用实现dao层实现类对象)
  • 使用了set注入以后,程序已经不再具有主动性,而是变成了被动的接受对象。把主动权交给了调用者,程序不用去管怎么创建,怎么实现了,它只负责提供一个接口。

这种思想,从本质上解决了问题,我们程序员不再去管理对象的创建了

系统的耦合性大大降低,可以更加专注的在业务上,这也就是IOC的原型!

  • 控制反转IOC(Inversion of Control),是一种思想(不去具体实现,而是提供set接口),DI(依赖注入)是实现IOC的一种方法;
  • 没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制;
  • 控制反转后,将对象的创建转移给第三方;
  • 控制反转(IOC)即获取依赖对象的方式反转了。

IOC是Spring框架的核心内容,使用多种方式完美的实现了IOC,可以使用XML配置,也可以实用注解,新版本的Spring也可以零配置实现IOC;

  • Spring容器在初始化时先读取配置文件,根据配置文件或元数据“创建与组织对象“存入容器中;
  • 程序使用时再从IOC容器中取出需要的对象。
  • 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的;

  • 而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到零配置的目的。

  • 控制反转是一种通过描述(XML或者注解),并通过第三方去生产或获取特定对象的方式。



 
  • Hello对象时谁创建的?

  • Hello对象的属性是怎么设置的?

    hello对象的属性是由Spring容器设置的,这个过程就叫控制反转

  • 控制:谁来控制对象的创建,传统应用程序是由程序本身控制创建的,使用Spring后,对象是由Spring来控制创建的

  • 反转:程序本身不创建对象,而变成被动的接收对象。

依赖注入:就是利用set方法来进行注入的。

IOC是一种编程思想,由主动地编程变成被动的接收

我们在案例一中,邢增一个Spring配置文件beans.xml


 
 
 
  • OK,到了现在,我们彻底不用在程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改。
  • 所谓IOC,一句话搞定:对象由Spring来创建,管理,装配
  1. 最开始dao层一个接口有多个实现类,service层引用接口并具体实现了其中一个实现类,用户(test)要想变更访问不同的dao层实现类,就需要去修改service层对dao层实现类的引用,从而需要修改了程序,主动权在程序手上,当此种需求较大时,程序修改起来很繁琐。

  2. 第一次修改:我们将service层对dao层实现类的引用,不去具体实现它,而是将接口变成属性,预留属性set接口。用户(test)想要使用哪个dao层实现类,只需要在test层调用serviceImpl时传入对应的dao层实现类对象,主动权在用户手上

    • 项目中的每一个类都去beans.xml中注册
    • 每个类的属性也都在注册时传入设置(注入),包括基本类型属性和引用类型属性(引用其他的对象)
    • 在项目构建的时候,Spring框架就会把所有的类的对象都构建出来,并且整个Spring中所有的对象只保留一份
  3. 要想修改service层中对dao层对象的引用,可以直接修改beans.xml配置文件,而无需修改程序。
  4. 控制:所有对象由Spring创建和管理
  5. 反转:通过beans.xml可以配置每个对象的属性及其引用的其他对象,选择权和主动权在用户手上(假设用户可以间接操作beans.xml)

 
 
 

test无需修改,只需修改上面beans.xml配置文件

4.1通过无参构造方法来创建


 
  • 此时已经初始化了所有管理的对象,User对象已经通过无参构造初始化了。

  • 该操作中Spring就已经创建和管理了所有在beans.xml中注册配置的对象。

  • 对象属性的配置,还是通过属性对应的set方法进行的。

4.2通过有参构造方法来创建

  • 此时不能在通过初始化实体类User了,因为那只有是无参构造方法时才能创建
  • 有参构造方法,采用配置属性

根据参数名字设置【常用】,后两种不常用



 

  • 同样也是Spring的context一旦获得,即配置文件加载的时候,所有的实体类都初始化了

  • 无论是通过无参构造,此时依靠set方法注入

  • 还是通过有参构造,此时通过有参构造直接注入

  • 可以某些属性通过有参构造,某些属性通过set注入

alias 为bean设置别名,可以设置多个别名


  • import,一般用于团队开发使用,可以在一个配置文件中导入其他配置文件,从而合并成一个
  • 假如项目中有多个人开发,不同人负责不同的类的开发,不同的类需要注册在不同的beans.xml中,此时我们可以利用import将所有人的beans.xml合并为一个总的。
  • 使用的时候,直接使用总的配置就可以了

 
  • **依赖:**bean对象的创建依赖于容器
  • 注入: bean对象中的所有属性,由容器注入,简而言之,就是为对象中属性赋值

6.1构造器注入(前面已讲)

无参构造方法注入==》就是利用set方法注入

set方法注入的类必须要有无参构造方法


 
 
 
 
 
 
 
 
 
 

6.3拓展方式注入(p命名空间注入、c命名空间注入)

  • p命名空间注入,还是利用无参构造方法注入(实体类中需要有无参构造方法)
  • c命名空间注入,是利用有参构造方法注入(实体类中需要有有参构造方法)

1.P命名空间注入 : 需要在头文件中加上约束文件

2.c命名空间注入 : 需要在头文件中加上约束文件

  • 本质上还是无参构造方法属性注入和有参构造方法注入
    • **无参构造方法注入:**即通过set方法注入,所以通过set方法注入时类中一定要有无参构造方法,但默认存在
    • **有参构造方法注入:**直接通过有参构造方法属性赋值注入,所以必须要重写有参构造方法;注意此时不要忘了显式添加一个无参构造方法,以适应set方法注入
  • p命名空间和c命名空间注入,本质上还是使用无参构造方法和有参构造方法注入

bean为每个类创建的对象,六种作用域:

1.单例模式(Spring默认机制:每次从容器中getBean的时候,拿到的是同一个对象)

2.原型模式(每次从容器中getBean的时候,都会产生一个新的对象)

  • 自动装配是使用spring满足bean依赖的一种方法
  • spring会在应用上下文中为某个bean寻找其依赖的bean依赖,即某个对象中引用的其他对象不用显式注入,spring可以实现自动注入。

Spring中bean中引用bean有三种装配机制,分别是

  1. 在java中显式配置;

  2. 隐式的bean发现机制和自动装配(本节研究的)

    组件扫描和自动装配,使得显式的配置降低到最少。

    实际应用中不推荐使用自动装配xml配置,而是使用注解装配。

测试环境搭建(XML显示装配引用bean)

2.新建两个实体类,Cat、Dog都有一个叫的方法


 

结果正常输出,环境ok

  • 2.再次测试,结果依旧成功输出

    3.如果将cat的id修改,和people属性名称不一致,此时按名称自动装配失败,空指针异常。

    因为byname规则实际上是按people属性的set方法找对应的bean去装配,此时找不到。

    1. 查找其类中所有引用的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat
    2. 去spring容器中寻找是否有此字符串名称id的对象
    3. 如果有,就取出注入,否则就报空指针异常
  • 使用时需要保证:同一类型的对象,在spring容器中唯一。否则会报不唯一异常。

    1. 此时被引用的bean的id名称无所谓了,可以去掉,因为是按照对象类型来寻找并自动装配的。

7.2 使用注解实现自动装配

  1. 在beans.xml配置文件中引入context文件头,注意学会修改方式配置文件


1.在实体类属性上采用@Autowired注解【推荐】

  • @Autowired是按照类型自动寻找匹配,不支持id名字匹配

  • 如在没有注册cat的bean时,people仍能成功注入,只是此时cat引用对象可以为空

  • @Resource:如有指定name属性,按照先按照指定id名称查找匹配

  • 再进行默认的byName方式查找装配

  • 以上都不成功,则按byType方式自动装配

    • 默认按类型装配(属于spring规范)
  • 名称可以通过name属性进行指定
  • 如果 没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找
  • 当找不到与名称匹配的bean时才按照类型进行装配
  • 它们作用相同,都是用注解方式注入对象,实现自动装配。但执行顺序不同:@Autowired先byType,@Resource先 byName。
  • 在Spring4之后,要是使用注解,必须保证aop的包的导入,导入Spring-webmvc会自动导入aop包
  • 使用注解需要导入contex约束,在增加对注解的支持

需要在beans.xml中配置扫描哪些包下的注解

  1. 
     
     
    
  2. 
    

开发中我们通常采用MVC三层架构

为了区分在不同的层中对其实现类,在Spring中进行注册装配bean

@Component有一些别名,功能都一样:都是注册bean对象

写上这些注解,就相当于将这个类交给Spring管理装配了!

一般在具体类前@Component下跟随书写

  • singleton:默认的,Spring会采用单例模式创建这个对象
  • prototype:原型模式,多例模式

小结 xml与注解比较

xml与注解 实现注册bean和注入属性 比较:

  • XML可以适用于任何场景,结构清晰,维护方便。适用于复杂类
  • 注解不是自己提供的类使用不了,开发方便。适用于简单类

**xml与注解 整合开发:**推荐做法

  • 使用过程中,可以不用扫描,扫描是为了类上的注解
  • JavaConfig原来是基于Spring的一个子项目,它通过Java类的方式提供Bean的定义信息

  • 采用此种配置方法,可以完全摒弃beans.xml配置文件

  1. 仍然采用注解注册bean,和进行属性注入

    
     
    
  2. 
     
    

这种纯Java的配置模式,在SpringBoot中随处可见!

为什么要学习代理模式,因为AOP的底层机制就是动态代理!

  • 抽象角色:一般使用接口或者抽象类实现
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色;代理真实角色后,一般会做一些附属的操作
  • 客户:使用代理角色来进行一些操作



 
 
 
 

在这个过程中,客户直接接触的就是中介,就如同现实生活中的样子,看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活。

  • 可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情
  • 公共的业务由代理来完成,实现了业务的分工
  • 公共业务发生扩展时变得更加集中和方便
  • 当类多了,每个类对应一个代理类;工作量就变大了,开发效率降低

我们想要静态代理的好处,又不想静态代理的缺点,所以,就有了动态代理。

同学们练习完毕后,我们再来举一个例子,巩固大家的学习!

  1. 创建一个抽象角色,比如咱们平时做的用户业务,抽象起来就是增删改查!

    
    
  2. 我们需要一个真实对象来完成这些增删改查操作

    
    
  3. 需求来了,现在我们需要增加一个日志功能,怎么实现?

    • 思路1:在实现类上增加代码(麻烦)
    • 思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好了
  4. 设置一个代理类来处理日志,代理角色

    
    

重点理解代理模式的思想:

我们不改变原来代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想

聊聊AOP:纵向开发、横向开发

  • 动态代理的角色和静态代理的一样
  • 动态代理的代理类是动态生成的,静态代理的代理类是我们提前写好的
  • 动态代理分为两类:一类是基于接口的动态代理,一类是基于类的动态代理
    • 基于接口的动态代理——JDK动态代理
    • 基于类的动态代理——cglib
    • 现在用的比较多的是javasist来生成动态代理
    • 我们这里使用JDK的原生代码来实现,其余道理都是一样的

AOP的原理就是java的动态代理机制

1. 在java的动态代理机制中,有两个重要的类或接口

首先我们我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:

  • 每个动态代理类都必须要实现InvocationHandler这个接口,InvocationHandler并不是动态代理类,动态代理类是动态生成的

  • 并且每个代理类的实例都管理了一个handler(代理类对象通过InvocationHandler接口关联动态生成的动态代理类)

  • 当我们通过代理对象调用一个方法的时候,这个方法的调用就被转发为由InvacationHandler这个接口的invoke方法来调用。

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢? proxy:  指代我们所代理的那个真实对象 method:  指代的是我们所要调用真实对象的某个方法的Method对象 args:  指代的是调用真实对象某个方法时接受的参数

Proxy这个类的作用就是用来创建一个代理对象的类。

它提供了许多方法,但是我们用的最多的就是==newProxyInstance这个方法:==

其接收三个参数,我们来看看这三个参数所代表的含义: interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

这个方法的作用就是得到一个动态的代理对象

2.通过一个实例来看看动态代理是什么样的

抽象方法:首先定义了一个Subject接口,为其声明两个办法



动态代理类:我们定义一个动态代理类,前面说到,每一个动态代理类都必须实现InvocationHandler这个接口


 
 
 
 
 
 

3.控制台的输出与分析

  • 我们可能会认为返回的代理对象会是Subject类型的对象,或者是InvocationHandler类型对象,可是都不是;

  • 首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?

    原因就在于newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现这组接口。这个时候我们可以将这个代理对象类型强转这组接口中的任意一个接口类型。

    是在JVM运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行时动态生成的一个对象,并且命名方式都是这样,以$开头,proxy为中,最后一个数字表示对象的标号。

  • 生产什么还需要Proxy中传入特定真实对象,从而生成相应的代理对象

  • 这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象 关联到的handler中的invoke方法中去执行。
  • 而我们的这个抽象代理dynamicProxy对象又接收了一个RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用dynamicProxy中的invoke方法去执行
  • 我们可以看到,在真正通过代理对象来调用真实对象的方法时,我们可以在该方法前后添加自己的一些操作。
  • ,正好是我们的Subject接口中的方法,这也就证明了当我通过代理对象来调用方法的时候,其实际上就是委托其关联到的dynamicProxy对象的invoke方法中调用,并不是自己来真实调用,而是通过代理的方式来调用。

这就是我们的java动态代理机制。

  • AOP是一种思想,是一种横向编程的思想,在不影响原来业务类的情况下,实现业务类的增强

  • 代理模式也是为了:“在不影响原来业务类的强狂下,实现业务类的增强”。所以AOP完全就是基于动态代理的Spring实现。

  • 代理模式本质就是装饰者模式。

  • 代理模式本质就是装饰者模式,在不影响原来业务类的情况下,实现业务类的增强
  • AOP就是代理模式在Spring中的实现
  • 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的 同一维护的一种技术。

  • AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式变成的一种衍生范型。

  • 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

提供声明式事务:允许用户自定义切面

AOP本质是动态代理用Spring实现,名词术语:

  • 横切关注点:对业务类增强的部分,即我们需要关注的部分,如日志、安全、缓存、事务等等…

  • 切面(ASPECT): 增强部分抽象的类

  • 通知(Advice): 增强部分抽象的类中的方法,切面要完成的工作

  • 目标(Target): 抽象接口,用来引用真实对象(动态代理中的InvocationHandler接口,动态代理类代理的是一个接口)

  • 代理(Proxy): 向目标对象应用通知后,创建的代理对象(动态代理中的Proxy类,生成动态代理对象)

  • 切入点(pointCut):切面通知 执行的地点的定义。

  • 连接点(JoinPoint):当采用around横切时,与切入点匹配的执行点。

即AOP 在不改变原有代码的情况下,去增加新的功能。

Spring中使用AOP,需要导入一个依赖包:


  • 增强类实现特定通知接口,即声明横切逻辑

  • 此时beans.xml中无需显式声明切面,只需声明切入点和执行环绕

首先我们编写业务接口和实现类,在com.kuang.service包下

然后去写我们的增强类,我们编写两个增强类,一个前值增强,一个后置增强,在com.kuang.log包下


 
 
 

最后去Spring的配置文件beans.xml中注册,并实现aop切入实现,注意导入aop约束


 
 
 
 

注意getBean返回的对象需要强转成抽象接口类型,因为增强类代理类实现的也是抽象接口类型

AOP的重要性:很重要,一定要理解其中的思路,主要是思想的理解。

Spring的AOP就是:将公共的业务(如日志、安全)等领域业务结合起来,当执行领域业务时,将会把公共业务加起来,实现公共业务代码的重复利用,领域业务更纯粹;程序猿专注领域业务,其本质还是动态代理。

方式2.自定义增强类来实现AOP(推荐使用)

1.第一步:写我们自己的一个原生切入类,在com.kuang.diy包下


 

采用自定义增强类,需要显式声明切面

采用Spring中API实现接口,在定义增强类时就实现了通知接口,所以在beans.xml中无需显式声明切面

1.编写一个注解实现的增强类,切面和通知 都使用注解在增强类值标注

2.配置beans.xml,注册bean,并增加支持注解的配置


  • 通过aop命名空间声明,为Spring容器中那些配置@Aspect切面的bean创建代理,植入切面
  • 有一个属性,默认为false,表示使用jdk动态 代理织入增强;为true时表示使用 CGLib动态代理技术植入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接 口,则spring将自动使用CGLib动态代理。


4.测试类(此处省略了工具类,直接创建SqlSession)

    • 
       
       
       
      
      • 它在修改MyBatis的基础配置时非常有用,基础配置通常指的是和

    • 获得SqlSession以后,就可以使用它来执行映射了的语句,提交或者回滚连接。

      • 模板可以参与到Spring的事务管理中,并且由于其是线程安全的,可以供多个映射器类使用。
      
       
      
    • 现在这个bean就可以直接注入到接口实现类的bean中;

11.1整合实现一(推荐):

  1. 
    
  2. 
     
     
     
    
  3. 
     
    
  4. 【重点】增加dao接口的实现类;私有化sqlSessionTemplate,采用构造方法注入,sql操作封装

    实现类注册bean实现

    
    

 
 
 
 
 
 
 
 

 

易错:xml文件中如果出现中文注释,可能会出错

  • 比起方式一,不需要管理SqlSessionTemplate,而且对事务的支持更加友好,可跟踪源码查看

  • 除了这些方式可以实现整合之外,我们还可以使用注解来实现,这个等我们后面学习SpringBoot的时候,还会测试整合!

Spring整合Mybatis时,配置文件分类与引用:


 

 
 
 
 
 
 
 

 
 
  • Spring中事务可以分为声明式事务和编程式事务
  • 编程式事务:代码中显示开启和关闭事务
  • 声明式事务:可以采用AOP横切的方式为所有方法或者特定方法添加事务
  1. 将上面Mybatis在Spring中的实现拷入新的项目中

  2. 在之前的案例中,我们给userMapper.java接口新增两个方法,删除和增加用户

    
    
  3. 没有进行事务的管理;我们想让他们都成功才算成功,有一个失败,就都失败,我们就应该需要事务!

    以前我们都需要自己手动管理事务,十分麻烦!

    但是Spring给我们提供了事务管理,我们只需要配置即可。

  • 在Spring中采用AOP为所有方法或者特定方法横切事务
  • Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制
  • Spring支持编程式事务和声明式事务管理
    • 编程式事务管理:事务管理代码嵌入业务方法,必须在每个事物操作业务逻辑中包含额外的事物管理代码;
    • 声明式事务管理:更好用,将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。将事务管理作为横切关注点,通过AOP方法模块化,Spring中通过Spring AOP框架支持声明式事务管理。
  1. 在Spring配置中管理事务,需要在beans.xml中导入头文件的约束:tx

  2. 在beans.xml中,配置事务管理器,得到Spring提供的事务管理器对象

    • 无论使用Spring的哪种事务管理策略(编程式或者声明式),事务管理器都是必须的
    • 就是Spring的核心事务管理抽象,管理封装了一组独立于技术的方法
  3. 采用AOP横切,将Spring的事务横切到所有方法或者特定方法

    • 
       
      

      Spring事务的传播特性:

      事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring支持7中事务传播行为:

      • required 没有事务就新建事务;已经存在一个事务,加入该事务
      • supports 有事务就支持,没有就没有
      • mandatory 有事务就支持,没有就抛异常
      • required_new 没有事务就新建事务,有事务把当前事务挂起
      • not_supported 非事务方式执行,有事务把当前事务挂起
      • never 不支持事务,有事务就抛出异常
      • nested 存在事务,嵌套事务;否则新建事务

      Spring默认的事务传播行为是required,适用于绝大多数情况

删除刚才插入的数据,再次测试;

此时我们发现所有方法都横切进入了事务,所有sql操作都成功才成功,否则失败。

为什么需要配置声明式事务?

  • 如果不配置,就需要我们手动提交控制事务;
  • 事务在项目开发过程中非常重要,涉及到数据的一致性问题,不容马虎!
  1. Spring主要是思想的学习,核心思想是IOC和AOP

    • 控制是指将所有的类托管给Spring创建管理控制
    • 反转是指通过属性依赖注入(DI)的方式,给对象的属性赋值,包括基本属性和引用属性(将对对象的控制权剥离处理)
    • 本质是装饰者模式和动态代理模式
    • 通过横切的方式在原有的业务代码中添加公共功能,而不改变原有业务代码

我要回帖

更多关于 为了方便记忆阅读和编程 的文章

 

随机推荐