Closed GitEngHar closed 2 months ago
Data アノテーション利用で生成されたメソッド
簡単に言うとクラス依存している部分を外部から呼び込んでくる
SpringFrameworkは任意で実装したクラスをインスタンス化する機能を持っている
インスタンスの生成はDIコンテナに任せる
以下を守ることでクラスの修正をなくすことができる??
@Component
を利用する @Component
によるインスタンス生成はステレオタイプアノテーションとよぶ 用途別に4種類ある。
@Controller
@Service
@Repository
上記には属さないが、@Component
は再利用されるクラスに付与される
サブ処理に用いられる
@Autowrited
@Component
を付け替えると 普段呼び出していた 実装クラスを切り替えることができる
@Autowired
でSpringスキャン時に生成されたインスタンを呼び出す
呼び出す側のコードを全く変更せずに、改修できる
これは「中心的な機能」と「横断的な機能」の2種類の考え方が存在する
横断的な機能は 共通する機能
ココでの考え方は共通する機能は呼び出して再利用することで開発者は中心的な機能に集中するということである
フィールドで注入を行う
セッターメソッドで注入を行う
コンストラクタで注入する
この場合、 @Autowired
のアノテーションを省略することができる
DIとは必要なものを用意して起き、必要なタイミングで利用する仕組みである
DIの注入パターンは前述の通り3パターンほど存在するが、推奨はコンストラクタインジェクションとなっている
コンストラクタでは final 宣言が主となっているため、 オブジェクトの不変性
が保たれ予測が容易いコードとなる
1クラスは1責任というが、コンストラクタパターンで注入をしているとこれに違反しているかどうかを発見しやすくなる
責任が混在するということはインスタンス化するオブジェクトが多くなることと同義であるため
重要なのは、プログラムの可読性 / 保守性 / 拡張性である
SOLID原則を意識するとわかりやすい
コンストラクタインジェクション
case 1
package com.example.demo.example.impl;
import org.springframework.stereotype.Component;
import com.example.demo.example.Example;
import com.example.demo.service.SomeService;
import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
public class ConstructorInjectionOmitExample implements Example {
private final SomeService someService;//finalを引数としたコンストラクタが自動で生成される
@Override
public void run() {
// TODO 自動生成されたメソッド・スタブ
someService.doService();
}
}
case2
package com.example.demo.example.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.example.demo.example.Example;
import com.example.demo.service.SomeService;
@Component
public class ConstructorInjectionExample implements Example {
private final SomeService someService;
@Autowired
public ConstructorInjectionExample(SomeService someService) {
this.someService = someService;
}
@Override
public void run() {
// TODO 自動生成されたメソッド・スタブ
someService.doService();
}
}
用語を図化
Aspect (横断的な機能の処理) は必要になった際にSpringFrameworkによって実行する
クラスにAspectを含めるのではなく、SpringFramework が生成した AOPProxy が横断的な処理が発生した際に、Aspectに処理を流す
Target
@Component
public class Target {
public void sayHelo() {
System.out.println( "Hello");
}
public void sayBay() {
System.out.println("Bay");
}
}
Around
@Around("execution(* com.example.demo.service.Target.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable{
long startTime = System.currentTimeMillis();
System.out.println("---[Around : Before]---");
System.out.println("Target");
System.out.println("Class : " + joinPoint.getSignature());
System.out.println("Method : " + joinPoint.getSignature().getName());
Object result = joinPoint.proceed();
System.out.println("---[Around After]---");
long elapsedTime = System.currentTimeMillis()- startTime;
System.out.println("Method execution time:" + elapsedTime + "millseconds.");
return result;
}
main
@SpringBootApplication
public class AopSampleApplication {
public static void main(String[] args) {
SpringApplication.run(AopSampleApplication.class, args)
.getBean(AopSampleApplication.class).exe();
}
@Autowired
private Target service; //DI
private void exe() {
service.sayHelo();
System.out.println("------");
service.sayBay();
}
}
結果
---[Around : Before]---
Target
Class : void com.example.demo.service.Target.sayHelo()
Method : sayHelo
Hello
---[Around After]---
Method execution time:1millseconds.
------
---[Around : Before]---
Target
Class : void com.example.demo.service.Target.sayBay()
Method : sayBay
Bay
---[Around After]---
Method execution time:0millseconds.
target 内に2つの簡単なメソッドが存在し、単純な実行をしている
ログをみるにクラス内のメソッド単位で aspect処理は実行されている
実行単位はおそらく以下で設定すると思われる
@Around("execution(* com.example.demo.service.Target.*(..))")
横断的な処理をまとめておき、必要な時に呼び出せる機能は、コード量の削減と記述忘れとめんどくさいが故の実装すっ飛ばしを担保してくれていい
こういうことだ!!
mvnと頭の中で被ってしまうようなぁ
プログラムを処理単位でわける考え方
以下のような感じ
題名 : 料理を作るシェフ
Model
料理を作るために必要な知識や作業
>> レシピ , 材料 など
View
料理を魅力的に見せるための盛り付け
>> 料理盛り付け
Controller
レシピ を見て 盛り付けを行ったり料理の振る舞いを調整
>> シェフ
それぞれに役割があるから分かりやすい!
お互いに依存関係が少ないので、あとあと追加しやすいし、テストしやすい
→ すぐに新しい料理も増やせるし、盛り付けパターンも増やせる
通称テンプレートエンジン
SpringBootと一緒の利用が推奨されており、一緒に使うと データを画面に表示する機能 を簡単にしてくれる
http://www.thymeleaf.org
#numbers.formatInteger(変数,整数最低桁数,"COMMA")
で利用できる
手法は2つある
<div th:fragment="header">
th:replace="common :: footer"
th:insert="common :: footer"
th:replace="~{layout ::base(~{::title}, ~{::body})}">
th:fragment="base(title,content)"
input で 値を渡して controllerで受け取る
大体の流れ
ここで値の受け取り方?(一部怪しい)は3種類くらいある
1つの 商品 には多くのレビューがつく
これはヒトツと多く => 1対多 の関係といえる
xml : resultMapの機能を使う オブジェクト : 商品の中にListでレビューが入ってくる
なお、別のテーブルにクエリをして結果をまとめているのは、JOINなのであしからず。
達成したいこと
5/22までにSQLの基本利用 join like ..etc 及び SpringFrameWorkを習得し、仕事の土俵に立つこと
期間と段取り
5/14 簡単なSpringフレームワークの利用 (超入門spring本完了)
5/18 オリジナル簡易Webアプリの作成 または EnglishManager をSpringに移行とバージョンアップ
重要なこと
目標に向けた段取りに齟齬がないことを知っておく