以下からの内容で、Baiduの百科事典:
AOP
あるAspect Oriented Programming
頭字語の意味:アスペクト指向プログラミング、動的に事前にコンパイルされ、実行モード中に機関によって実装統一プログラムの機能を維持するための技術。AOP
あるOOP
継続は、ソフトウェア開発のホットスポットですが、また、Spring
フレームワークの重要な要素は、関数型プログラミングYanshengファンタイプです。この使用AOP
により、ビジネスロジックのさまざまな部分を分離できるため、ビジネスロジックのさまざまな部分間の結合が減り、プログラムの再利用性が向上し、同時に開発の効率が向上します。
1.静的プロキシ
プロジェクト開発の過程で、そのような合意された考えがあります:機能の拡張は、元の機能を変更せずに拡張する必要があります。次に、第3号のエージェントを紹介する必要があります。この種の考え方Service
は、前のレイヤーでよりよく実現されています。たとえば、特定のServiceImpl
クラスを展開する必要がある場合は、このService
インターフェイスを実装するための追加のクラスを記述してから、追加する必要のあるコードを追加できます。このタイプのプロキシは静的プロキシでもあります。たとえば、次の例:
public interface UserDao {
String getUserName();
}
public class UserDaoImpl implements UserDao{
public String getUserName() {
return "张三";
}
}
public interface UserService {
String getUserInfo();
}
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public String getUserInfo() {
return userDao.getUserName();
}
}
たとえば、この時点でテストします。
@Test
public void getUserInfoTest(){
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl());
System.out.println(userService.getUserInfo());
}
そこに行くgetUserInfo
たびに追加情報を照会する必要がある場合は、プロキシクラスを使用してこれを実行する必要があります。
public class proxy implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public String getUserInfo() {
doSomething();
return userDao.getUserName();
}
private void doSomething() {
System.out.println("做一些事情");
}
}
@Test
public void getUserInfoTest(){
proxy userServiceProxy = new proxy();
userServiceProxy.setUserDao(new UserDaoImpl());
System.out.println(userServiceProxy.getUserInfo());
}
このアイデアは、アダプタモードと同様に、主に元のコードを変更せずに一部の関数を追加するのに適しています。これは、静的プロキシモードとも呼ばれます。このアプローチの主な欠点は、場合ということですA
、B
結果はコードの重複の多くを書くことで明らかである、...それのすべてがカスタマイズされて、複数のプロキシクラスを追加しました。したがって、ここでは動的プロキシモードを導入する必要があります。
2.動的プロキシ
現時点では、いくつかの新しい関数を追加するときに、多くのクラスを追加したり、多くの反復コードを追加したりしないことを望んでいます。ここで使用する必要があるテクニックJava
は、真ん中の反射です。
動的エージェントは、次の2つのカテゴリに分類できます。
- インターフェイスベース-JDK動的プロキシ。
- クラスベース–cglib;
- Javaバイトコードの実装。
使用する必要がInvocationHandler
あり、Proxy
2つのクラス:
InvocationHandler
:ハンドラーを呼び出して結果を返します。Proxy
:動的プロキシのこのインスタンスを生成するために使用される動的プロキシクラスとインスタンスを作成するための静的メソッドを提供します。
この時点で、プロキシクラスを削除してから、動的プロキシを実装proxy
するためのInvocationHandler
インターフェイスを実装するクラスを作成します。
まず、今回のニーズを明確にするかService
、エージェントを使って行う必要のあるレイヤーの機能を拡張します。
public class MyInvocationHandler implements InvocationHandler {
// 需要扩充的接口对象【或者,需要代理的接口对象】
UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
// 生成代理类对象,也就是需要扩充的接口对象UserService
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
userService.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 新增功能调用
doSomethings();
// 传入需要动态代理的对象
return method.invoke(userService, args);
}
// 这里是扩充内容
private void doSomethings(){
System.out.println("做一些事情。");
}
}
テストするには、前のServiceImpl
セクションで次のような文を印刷することをお勧めします。
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public String getUserInfo() {
System.out.println("以前的getUserInfo接口的扩充");
return userDao.getUserName();
}
}
テスト:
@Test
public void getUserInfoTest(){
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl());
MyInvocationHandler handler = new MyInvocationHandler();
handler.setUserService(userService);
// 新的UserService对象,实现了新增功能,但是我们这里并没有去真的用类来创建
UserService userService1 = (UserService) handler.getProxy();
System.out.println(userService1.getUserInfo());
}
つまり、UserServiceImpl
今回は元のプロジェクトのクラスを変更せず、プロジェクトの実行時に元のgetUserInfo
関数が呼び出され、要件の新しい関数が呼び出されました。
- 動的プロキシクラスは、対応するインターフェイスが実装されている限り、複数のクラスをプロキシできます。
- プロキシがインターフェースである動的プロキシクラス、プロキシは一種のビジネスです。