Javaインタビュー質問の全集(15)
BaiyuITハハ
141. HibernateのDetachedCriteriaクラスは何をしますか?
回答:DetachedCriteriaとCriteriaの使用法は基本的に同じですが、CriteriaはSessionのcreateCriteria()メソッドによって作成されます。つまり、Criteriaはそれを作成したSessionなしでは使用できません。DetachedCriteriaは、セッションなしで(DetachedCriteria.forClass()メソッドを使用して)作成できるため、通常はオフラインCriteriaと呼ばれ、クエリ操作が必要なときにSessionにバインドされます(getExecutableCriteria(Session)メソッドを呼び出します)。これは、必要に応じてDetachedCriteriaを別のセッションにバインドできることも意味します。
142. @OneToManyアノテーションのmappedBy属性の機能は何ですか?
回答:@OneToManyは、1対多の関連付けマッピングを構成するために使用されますが、通常、1対多の関連付けマッピングは、学生やクラスなどの複数の関係者によって維持されます。学生を維持するために、クラス属性を学生クラスに追加する必要があります。クラスの関連付けの関係(データベースでは、studentテーブルの外部キークラス番号は、studentテーブルとclassテーブルの間の多対1の関係を維持します)。双方向の関連付けを使用する場合は、クラスクラスにコンテナ属性を追加して、生徒を格納します。また、マッピングには@OneToManyアノテーションを使用します。現時点では、mappedBy属性が非常に重要です。構成にXMLを使用する場合は、<set>タグのinverse = "true"設定を使用して、同じ効果を実現できます。
143. MyBatisでプレースホルダーを書き込むために#と$を使用することの違いは何ですか?
回答:#受信データを文字列として扱い、受信データに自動的に引用符を追加します。$は受信データをSQLで直接表示します。注:$プレースホルダーを使用すると、SQLインジェクションが発生する可能性があります***。#を使用できる場所では$を使用しないでください。orderby句を記述する場合は、#の代わりに$を使用する必要があります。
144.MyBatisでの名前付けの役割を説明します。
回答:大規模なプロジェクトでは、多数のSQLステートメントが存在する可能性があります。現時点では、各SQLステートメントに一意の識別子(ID)を割り当てるのは簡単ではありません。この問題を解決するために、MyBatisでは、マッピングファイルごとに一意の名前名を設定して、このマッピングファイルで定義された各SQLステートメントがこの名前名で定義されたIDになるようにすることができます。このIDが各名前空間で一意であることを確認できる限り、異なるマッピングファイルのステートメントIDが同じであっても、競合は発生しません。
145. MyBatisの動的SQLとはどういう意味ですか?
回答:複雑なクエリの中には、複数のクエリ条件を指定する場合がありますが、これらの条件が存在する場合と存在しない場合があります。たとえば、58の同じ都市で家を探す場合、家を見つけるためのエリア、フロア、場所を指定できます。面積、価格、家の種類、場所を指定して家を探すことも可能ですが、その際、ユーザーが指定した条件に応じて動的にSQL文を生成する必要があります。永続化レイヤーフレームワークを使用しない場合は、SQLステートメントを自分でアセンブルする必要があるかもしれません。幸い、MyBatisはこの問題を解決するための動的SQL関数を提供します。MyBatisで動的SQLを実装するために使用される主な要素は次のとおりです。
- if
- choose / when / otherwise
- trim
- where
- set
- foreach
以下は、マッピングファイルのスニペットです。
<select id="foo" parameterType="Blog" resultType="Blog">
select * from t_blog where 1 = 1
<if test="title != null">
and title = #{title}
</if>
<if test="content != null">
and content = #{content}
</if>
<if test="owner != null">
and owner = #{owner}
</if>
</select>
もちろん、次のように書くこともできます。
<select id="foo" parameterType="Blog" resultType="Blog">
select * from t_blog where 1 = 1
<choose>
<when test="title != null">
and title = #{title}
</when>
<when test="content != null">
and content = #{content}
</when>
<otherwise>
and owner = "owner1"
</otherwise>
</choose>
</select>
次の例をもう一度見てください。
<select id="bar" resultType="Blog">
select * from t_blog where id in
<foreach collection="array" index="index"
item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
146. IoCとDIとは何ですか?DIはどのように実装されますか?
回答:IoCはInversion of Controlと呼ばれ、Inversion of Controlの略です。DI(依存関係インジェクション)は依存関係インジェクションと呼ばれ、IoCのより単純な解釈です。制御の反転とは、従来はプログラムコードによって直接制御されていたオブジェクトの呼び出し権をコンテナに転送することであり、オブジェクトコンポーネントのアセンブリと管理はコンテナを介して実現されます。いわゆる「制御の反転」は、プログラムコード自体から外部コンテナへのコンポーネントオブジェクトに対する制御の転送であり、コンテナはオブジェクトを作成し、オブジェクト間の依存関係を管理します。IoCは、ハリウッドの原則を具体化しています-「私に電話しないでください、私たちはあなたに電話します」。依存関係の注入の基本原則は、アプリケーションコンポーネントがリソースやその他の依存する協調オブジェクトの検索を担当してはならないということです。コンテナはオブジェクトの構成を担当する必要があり、リソースを検索するためのロジックは、アプリケーションコンポーネントのコードから抽出され、コンテナに渡されて完了します。DIは、IoCのより正確な説明です。つまり、コンポーネント間の依存関係は、実行時にコンテナによって決定されます。より鮮明に言うと、コンテナは特定の依存関係をコンポーネントに動的に注入します。
例:クラスAはインターフェイスBのメソッドを使用する必要があり、次にクラスAとインターフェイスBの間の関連付けまたは依存関係を確立する必要があります。最も基本的な方法は、クラスAのインターフェイスBを実装するクラスCのインスタンスを作成することです。 、ただし、この方法では、開発者は2つの間の依存関係を維持する必要があります。つまり、依存関係が変更された場合は、コードを変更してシステム全体を再構築する必要があります。これらのオブジェクトとその依存関係をコンテナを介して管理する場合は、クラスAのインターフェイスBを関連付けるために使用するメソッド(コンストラクタまたはセッターメソッド)を定義し、クラスAの実装クラスCとインターフェイスBをに配置するだけで済みます。コンテナでは、2つの間の関連付けは、コンテナの構成によって実現されます。
依存関係の注入は、セッターメソッドインジェクション(設定インジェクション)、コンストラクターインジェクション、インターフェイスインジェクションによって実現できます。Springはセッターインジェクションとコンストラクターインジェクションをサポートします。通常、コンストラクターインジェクションは必要な依存関係を注入するために使用されます。依存関係、セッターインジェクションの方が適しています。セッターインジェクションでは、オブジェクトを作成するために、パラメーターなしのコンストラクターまたはパラメーターなしの静的ファクトリメソッドを提供するクラスが必要です。
147.春のビーンの範囲は何ですか?
回答:Springの初期バージョンでは、スコープはシングルトンとプロトタイプの2つだけです。前者は、Beanがシングルトンとして存在することを意味し、後者は、Beanがコンテナーから呼び出されるたびに、新しいインスタンス、プロトタイプが返されることを意味します。通常、プロトタイプに変換されます。
補足:デザインモードの作成モードにはプロトタイプモードもあります。プロトタイプモードも一般的に使用されるモードです。たとえば、インテリアデザインソフトウェアを作成するには、すべてのマテリアルがツールボックスにあり、ツールボックスを取り出すたびにマテリアルオブジェクトのプロトタイプであるプロトタイプモードは、オブジェクトのクローン作成によって実現できます。
Spring 2.xでは、WebApplicationContextに3つの新しいスコープが追加されました。つまり、リクエスト(HTTPリクエストごとに新しいBeanが作成されます)、セッション(同じHttpSessionが同じBeanを共有し、異なるHttpSessionが異なるBeanを使用します)そしてglobalSession(同じグローバルセッションがBeanを共有します)。
説明:シングルトンモードとプロトタイプモードはどちらも重要な設計パターンです。一般に、状態のないクラスまたは不変の状態のクラスは、シングルトンモードに適しています。従来の開発では、DAOはスレッドセーフではないオブジェクトであるConnectionを保持しているため、シングルトンモードは使用されませんが、Spring環境では、SpringがJava APIでAOPとThreadLocalを使用するため、すべてのDAOクラスペアでシングルトンモードを採用できます。スレッドセーフオブジェクトは特別に扱われます。
ThreadLocalは、マルチスレッドプログラムの同時実行性の問題を解決するための新しいアイデアを提供します。ThreadLocalは、その名前が示すように、スレッドのローカライズされたオブジェクトです。複数のスレッドで動作するオブジェクトがThreadLocalを使用して変数を維持する場合、ThreadLocalは、変数を使用するスレッドごとに独立した変数コピーを割り当てるため、各スレッドを個別に変更できます。他のスレッドの対応するものに影響を与えることなく、それ自体のコピー。スレッドの観点からは、この変数はスレッドのローカル変数のようなものです。
ThreadLocalクラスは非常にシンプルで使いやすいです。メソッドは4つしかなく、次の3つのメソッドを使用できます。
- void set(T value):現在のスレッドのスレッドローカル変数の値を設定します。
- T get():現在のスレッドに対応するスレッドローカル変数の値を取得します。
- void remove():現在のスレッドのスレッドローカル変数の値を削除します。
ThreadLocalは、スレッドごとに変数の独立したコピーをどのように維持しますか?ThreadLocalクラスにMapがあり、キーはスレッドオブジェクトであり、値はスレッドに対応する変数のコピーです。ThreadLocalクラスを自分でシミュレートすることは難しくありません。コードは次のとおりです。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class MyThreadLocal<T> {
private Map<Thread, T> map = Collections
.synchronizedMap(new HashMap<Thread, T>());
public void set(T newValue) {
map.put(Thread.currentThread(), newValue);
}
public T get() {
return map.get(Thread.currentThread());
}
public void remove() {
map.remove(Thread.currentThread());
}
}
148. AOP(アスペクト指向プログラミング)と呼ばれるものを説明してください。
回答:AOP(Aspect-Oriented Programming)は、アスペクトと呼ばれる言語構造に基づくプログラミングパラダイムを指します。アスペクトは、分散を記述するために使用される新しいモジュラーメカニズムです。オブジェクト、クラス、またはメソッドにおける分野横断的な懸念。
149.「横断的注意」の概念をどのように理解しますか?
回答:「横断的注意」は、アプリケーション全体の注意機能に影響を与えます。通常のビジネスロジックと直交しており、必要な接続はありませんが、ほとんどすべてのビジネスロジックにこれらの注意機能が含まれています。通常、トランザクション、ログ、セキュリティなどの懸念事項は、アプリケーションの分野横断的な懸念事項です。
150. AOPのJoinpoint、Pointcut、Advice、Introduction、Weaving、およびAspectの概念をどのように理解しますか?
回答:
a。結合点:プログラム実行の特定の位置(たとえば、メソッドが呼び出される前後、メソッドが例外をスローした後)。クラスまたはプログラムコードの一部には、境界プロパティを持つ特定のポイントがいくつかあり、これらのコードの特定のポイントは接続ポイントです。Springはメソッドの接続ポイントのみをサポートします。
b。ポイントカット:接続ポイントがデータ内のレコードと同等である場合、ポイントカットはクエリ条件と同等であり、1つのポイントカットが複数の接続ポイントと一致する可能性があります。Spring AOPのルール解析エンジンは、カットポイントによって設定されたクエリ条件を解析し、対応する接続ポイントを見つける役割を果たします。
c。拡張(アドバイス):拡張は、ターゲットクラスの接続ポイントに組み込まれたプログラムコードの一部です。Springが提供する拡張インターフェースはすべて、BeforeAdvice、AfterReturningAdvice、ThrowsAdviceなどの場所名が付いています。多くの資料が拡張機能を「通知」に翻訳しましたが、これは明らかに不十分な翻訳であり、多くのプログラマーを長い間困惑させてきました。
注:アドバイスは、多くの国内の書面で「通知」として翻訳されていますが、明らかにこの翻訳はその本質を表現できません。この単語を「強化された」と翻訳するいくつかの読み物があります。この翻訳はアドバイスに対してより正確です。解釈では、AOPを介して元のビジネスロジックに横断的注意機能を追加します。これは元のビジネスロジックの拡張です。この拡張には、事前拡張、事後拡張、返品後拡張、および例外スローがあります。時間の強化と周囲の強化。
d。はじめに(はじめに):はじめには、クラスにいくつかの属性とメソッドを追加する特別な拡張機能です。このように、元々ビジネスクラスが特定のインターフェースを実装していなくても、導入機能により、インターフェースの実装ロジックを動的にビジネスクラスに追加し、ビジネスクラスをこのインターフェースの実装クラスにすることができます。
e。ウィービング:ウィービングは、ターゲットクラスの特定の接続ポイントに拡張機能を追加するプロセスです。AOPには3つのウィービングメソッドがあります。①コンパイル時ウィービング:特別なJavaコンパイル期間(たとえば、AspectJのajc)が必要です。 ②ロード期間ウィービング:クラスをロードするときにクラスを拡張するために特別なクラスローダーを使用する必要があります。③ランタイムウィービング:実行時に拡張を実現するためにターゲットクラスのプロキシを生成します。Springは動的プロキシを使用してランタイムウィービングを実装し、AspectJはコンパイル時ウィービングとロード時ウィービングを使用します。
f。アスペクト:アスペクトは、接点と拡張(はじめに)で構成されます。これには、横断的注意機能の定義と接続点の定義が含まれます。
補足:プロキシモードは、GoFによって提案された23のデザインパターンの中で最も古典的なパターンの1つです。プロキシモードはオブジェクトの構造モードです。オブジェクトのプロキシオブジェクトを提供し、プロキシオブジェクトは元のオブジェクトへの参照を制御します。簡単に言えば、プロキシオブジェクトは元のオブジェクトよりも多くの責任を果たすことができます。元のオブジェクトに横断的な注意を追加する必要がある場合は、元のオブジェクトのプロキシオブジェクトを使用できます。OfficeシリーズのWordドキュメントを開くと、ドキュメントにイラストがある場合、ドキュメントが読み込まれると、ドキュメント内のイラストは破線のプレースホルダーになります。ユーザーが実際にページを表示して画像を表示したい場合は、この画像を実際にロードするには、実際にはプロキシモードを使用します。実際の画像を置き換える仮想ボックスは仮想プロキシです。Hibernateのloadメソッドも仮想プロキシオブジェクトを返し、ユーザーがオブジェクトのプロパティにアクセスするのを待ってからデータベースに送信します。 SQLステートメントを発行して、実際のオブジェクトを取得します。
プロキシモードの使用を実証するためにテストを受けるガンマンを見つける例を次に示します。
/**
* 参考人员接口
* @author 骆昊
*
*/
public interface Candidate {
/**
* 答题
*/
public void answerTheQuestions();
}
/**
* 懒学生
* @author 骆昊
*/
public class LazyStudent implements Candidate {
private String name; // 姓名
public LazyStudent(String name) {
this.name = name;
}
@Override
public void answerTheQuestions() {
// 懒学生只能写出自己的名字不会答题
System.out.println("姓名: " + name);
}
}
/**
* 枪手
* @author 骆昊
*/
public class Gunman implements Candidate {
private Candidate target; // 被代理对象
public Gunman(Candidate target) {
this.target = target;
}
@Override
public void answerTheQuestions() {
// 枪手要写上代考的学生的姓名
target.answerTheQuestions();
// 枪手要帮助懒学生答题并交卷
System.out.println("奋笔疾书正确答案");
System.out.println("交卷");
}
}
public class ProxyTest1 {
public static void main(String[] args) {
Candidate c = new Gunman(new LazyStudent("王小二"));
c.answerTheQuestions();
}
}
注:JDK 1.3以降、Javaは動的プロキシテクノロジーを提供し、開発者が実行時にProxyクラスやInvocationHandlerインターフェイスなどのインターフェイスのプロキシインスタンスを作成できるようにします。次の例では、動的プロキシを使用してArrayListのプロキシを記述します。要素を追加および削除すると、追加または削除された要素とArrayListのサイズがコンソールに出力されます。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
public class ListProxy<T>
implements InvocationHandler {
private List<T> target;
public ListProxy(List<T> target) {
this.target = target;
}
@Override
public Object invoke(Object proxy,
Method method, Object[] args)
throws Throwable {
Object retVal = null;
System.out.println("[" + method.getName() + ": "
+ args[0] + "]");
retVal = method.invoke(target, args);
System.out.println("[size=" + target.size() + "]");
return retVal;
}
}
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ProxyTest2 {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
Class<?> clazz = list.getClass();
ListProxy<String> myProxy = new ListProxy<String>(list);
List<String> newList = (List<String>)
Proxy.newProxyInstance(clazz.getClassLoader(),
clazz.getInterfaces(), myProxy);
newList.add("apple");
newList.add("banana");
newList.add("orange");
newList.remove("banana");
}
}
注:Javaの動的プロキシを使用する際の制限の1つは、プロキシクラスがインターフェイスを実装する必要があることです。インターフェイス指向のプログラミングはすべての優れたJavaプログラムが知っているルールですが、現実は満足のいくものではないことがよくあります。インターフェイスを実装しないクラスの場合そのプロキシを生成する方法は?継承!継承は、既存のコードの機能を拡張するための最も古典的な方法です。継承は初心者によって悪用されることがよくありますが、上級プログラマーによって無視されることがよくあります。CGLibは、非常に低レベルのバイトコード生成テクノロジを使用して、クラスのサブクラスを作成することでプロキシを生成します。これは、Javaの動的プロキシの欠点を補います。したがって、動的プロキシとSpringのCGLibはどちらも、インターフェイスの実装に役立つプロキシを作成するための重要な手段です。クラスは動的プロキシを使用してそのプロキシクラスを生成し、インターフェイスを実装しないクラスはCGLibを使用して継承を通じてそのプロキシを作成します。