Spring AOP 이해

12669 단어 springaop
하나.앞말
이전의 프로젝트에서spring aop의 구체적인 실현과 이론에 관심을 가지는 경우는 드물었다. 단지 aop이 구체적으로 어떻게 사용되는지 간단하게 이해했고 박문을 잘 쓴 것을 보고 공부를 했다.
AOP
AOP(Aspect Oriented Programming), 즉 절단면 프로그래밍은 OOP(Object Oriented Programming, 대상 프로그래밍)의 보완과 보완이라고 할 수 있다.OOP는 봉인, 계승, 다태적 등 개념을 도입하여 대상 차원 구조를 구축하여 공공 행위를 모의하는 집합에 사용한다.그러나 OOP는 개발자가 세로 관계를 정의할 수 있지만 로그 기능과 같은 가로 관계를 정의하는 데는 적합하지 않다.로그 코드는 모든 대상 차원에 가로로 흩어져 있지만 그에 대응하는 대상의 핵심 기능과 아무런 관계가 없다. 예를 들어 안전성, 이상 처리와 투명한 지속성도 마찬가지다. 이런 곳곳에 흩어져 있는 무관한 코드는 횡단(cross cutting)이라고 불리는데 OOP 디자인에서 대량의 코드의 중복을 초래하고 각 모듈의 중용에 불리하다.
AOP 기술은 정반대로'횡단'이라고 불리는 기술을 이용하여 봉인된 대상의 내부를 해부하고 여러 종류의 공공 행위에 영향을 미치는 것을 중용 모듈로 봉인하여'Aspect', 즉 절면이라고 명명한다.이른바'절단면'은 간단하게 말하면 업무와 무관하지만 업무 모듈에 공통적으로 호출되는 논리나 책임을 봉인하면 시스템의 중복 코드를 줄이고 모듈 간의 결합도를 낮추며 미래의 조작성과 유지보수성에 유리하다.
'횡단'기술을 사용하여 AOP는 소프트웨어 시스템을 두 부분으로 나눈다. 그것이 바로 핵심 관심사와 횡단 관심사이다.업무 처리의 주요 절차는 핵심 관심사이고 그와 관계가 크지 않은 부분은 횡단 관심사이다.횡단 관심점의 특징 중 하나는 그들이 핵심 관심점의 여러 곳에서 자주 발생하고 각 지역은 기본적으로 비슷하다는 것이다. 예를 들어 권한 인증, 로그, 사물 등이다.AOP의 역할은 시스템의 각종 관심사를 분리하고 핵심 관심사와 횡단 관심사를 분리하는 데 있다.
AOP 핵심 개념
1. 횡단 관심점
어떤 방법에 대해 차단을 하고, 차단한 후에 어떻게 처리하는지, 이런 관심사를 횡단 관심사라고 부른다
2. 절단면(aspect)
유형은 물체 특징에 대한 추상이고, 절단면은 횡단 관심점에 대한 추상이다
3. 연결점(joinpoint)
차단된 점, 스프링은 메소드 유형의 연결점만 지원하기 때문에 스프링에서 연결점은 차단된 방법을 가리키며, 실제 연결점은 필드나 구조기일 수도 있다
4, 삽입점(pointcut)
연결점을 차단하는 정의
5. 알림(advice)
알림이란 연결점에 가로막힌 후 실행할 코드를 가리키며, 알림은 전치, 후치, 이상, 최종, 주위 알림 다섯 종류로 나뉜다
6. 대상 객체
에이전트의 대상 객체
7, 짜임 (weave)
대상 객체에 탄젠트를 적용하고 프록시 객체를 생성하는 프로세스
8. 도입(introduction)
코드를 수정하지 않는 전제에서 운행 기간에 클래스를 동적으로 추가할 수 있는 방법이나 필드를 도입한다
Spring AOP 지원
Spring에서 AOP 에이전트는 Spring의 IOC 용기가 생성, 관리를 맡고 의존 관계도 IOC 용기가 관리한다.따라서 AOP 에이전트는 용기에 있는 다른 bean 실례를 직접 사용하여 목표를 삼을 수 있으며, 이러한 관계는 IOC 용기의 의존 주입에서 제공할 수 있다.Spring 프록시 생성 규칙은 다음과 같습니다.
1. 기본적으로 Java 동적 에이전트를 사용하여 AOP 에이전트를 만들면 모든 인터페이스 인스턴스에 에이전트를 만들 수 있습니다.
2. 프록시가 필요한 클래스가 프록시 인터페이스가 아닌 경우 Spring은 CGLIB 프록시를 사용하거나 CGLIB를 강제로 사용하도록 전환합니다.
AOP 프로그래밍은 사실 매우 간단한 일이다. AOP 프로그래밍을 보면 프로그래머는 세 부분만 참여해야 한다.
1. 일반 업무 구성 요소 정의
2. 접점을 정의하고 하나의 접점은 여러 개의 업무 구성 요소를 횡단할 수 있다
3. 증강 처리를 정의한다. 증강 처리는 AOP 프레임워크에서 일반 업무 구성 요소를 짜는 처리 동작이다
그래서 AOP 프로그래밍을 하는 관건은 바로 접점 정의와 증강 처리를 정의하는 것이다. 적당한 접점과 증강 처리를 정의하면 AOP 프레임워크는 자동으로 AOP 프록시를 생성한다. 즉, 프록시 대상의 방법 = 증강 처리 + 피프록시 대상의 방법을 생성한다.
다음은 Spring AOP의.xml 파일 템플릿, 이름은 aop입니다.xml, 그 후의 내용은 모두 aop에 있습니다.xml에서 확장:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
   
</beans> 
Spring 기반 AOP 단순화
주의해서 설명하기 전에 한 가지 설명: Spring AOP를 사용하여 코드를 성공적으로 실행하려면 Spring에서 개발자에게 제공하는jar 패키지만으로는 부족합니다. 추가로 인터넷에서 두 개의jar 패키지를 다운로드하십시오.
1、aopalliance.jar
2、aspectjweaver.jar
Spring AOP의 XML 구현 방법에 대한 설명을 시작하고 인터페이스를 정의합니다.

public interface HelloWorld
{
 void printHelloWorld();
 void doPrint();
} 
두 인터페이스 구현 클래스를 정의합니다.

public class HelloWorldImpl1 implements HelloWorld
{
 public void printHelloWorld()
 {
  System.out.println("Enter HelloWorldImpl1.printHelloWorld()");
 }
 
 public void doPrint()
 {
  System.out.println("Enter HelloWorldImpl1.doPrint()");
  return ;
 }
} 


public class HelloWorldImpl2 implements HelloWorld
{
 public void printHelloWorld()
 {
  System.out.println("Enter HelloWorldImpl2.printHelloWorld()");
 }
 
 public void doPrint()
 {
  System.out.println("Enter HelloWorldImpl2.doPrint()");
  return ;
 }
} 
인쇄 시간:

public class TimeHandler
{
 public void printTime()
 {
  System.out.println("CurrentTime = " + System.currentTimeMillis());
 }
} 
이 세 가지 종류가 있으면 간단한 Spring AOP를 실현할 수 있습니다. aop을 보세요.xml 구성:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
  
  <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
  <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
  <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
  
  <aop:config>
   <aop:aspect id="time" ref="timeHandler">
    <aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
    <aop:before method="printTime" pointcut-ref="addAllMethod" />
    <aop:after method="printTime" pointcut-ref="addAllMethod" />
   </aop:aspect>
  </aop:config>
</beans> 

main 함수를 써서 호출합니다.

public static void main(String[] args)
{
 ApplicationContext ctx = 
   new ClassPathXmlApplicationContext("aop.xml");
  
 HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1");
 HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2");
 hw1.printHelloWorld();
 System.out.println();
 hw1.doPrint();
 
 System.out.println();
 hw2.printHelloWorld();
 System.out.println();
 hw2.doPrint();
} 

실행 결과:

CurrentTime = 1446129611993
Enter HelloWorldImpl1.printHelloWorld()
CurrentTime = 1446129611993

CurrentTime = 1446129611994
Enter HelloWorldImpl1.doPrint()
CurrentTime = 1446129611994

CurrentTime = 1446129611994
Enter HelloWorldImpl2.printHelloWorld()
CurrentTime = 1446129611994

CurrentTime = 1446129611994
Enter HelloWorldImpl2.doPrint()
CurrentTime = 1446129611994 
HelloWorld 인터페이스에 두 가지 구현 클래스의 모든 방법에 에이전트가 추가된 것을 보았습니다. 에이전트 내용은 인쇄 시간입니다.
Spring 기반 AOP 추가 세부 사항 사용
1、Java 클래스에서 로그를 인쇄하는 횡단 접점 추가:

public class LogHandler
{
 public void LogBefore()
 {
  System.out.println("Log before method");
 }
 
 public void LogAfter()
 {
  System.out.println("Log after method");
 }
} 


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
  
  <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
  <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
  <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
  <bean id="logHandler" class="com.xrq.aop.LogHandler" />
  
  <aop:config>
   <aop:aspect id="time" ref="timeHandler" order="1">
    <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
    <aop:before method="printTime" pointcut-ref="addTime" />
    <aop:after method="printTime" pointcut-ref="addTime" />
   </aop:aspect>
   <aop:aspect id="log" ref="logHandler" order="2">
    <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
    <aop:before method="LogBefore" pointcut-ref="printLog" />
    <aop:after method="LogAfter" pointcut-ref="printLog" />
   </aop:aspect>
  </aop:config>
</beans> 

테스트 클래스는 변경되지 않으며 인쇄 결과는 다음과 같습니다.

CurrentTime = 1446130273734
Log before method
Enter HelloWorldImpl1.printHelloWorld()
Log after method
CurrentTime = 1446130273735

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl1.doPrint()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl2.printHelloWorld()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273737
Log before method
Enter HelloWorldImpl2.doPrint()
Log after method
CurrentTime = 1446130273737 

logHandler를 timeHandler 앞에서 사용하려면 두 가지 방법이 있습니다.
(1)aspect 안에 하나의order 속성이 있다.order 속성의 숫자는 바로 관심점을 횡단하는 순서이다
(2) logHandler를 timeHandler 앞에 정의하고 Spring은 기본적으로 aspect의 정의 순서를 직입 순서로 한다
2. 나는 단지 인터페이스에 짜는 몇 가지 방법만 원한다
포인트컷의 expression을 수정하면 됩니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
  
  <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
  <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
  <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
  <bean id="logHandler" class="com.xrq.aop.LogHandler" />
  
  <aop:config>
   <aop:aspect id="time" ref="timeHandler" order="1">
    <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.print*(..))" />
    <aop:before method="printTime" pointcut-ref="addTime" />
    <aop:after method="printTime" pointcut-ref="addTime" />
   </aop:aspect>
   <aop:aspect id="log" ref="logHandler" order="2">
    <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.do*(..))" />
    <aop:before method="LogBefore" pointcut-ref="printLog" />
    <aop:after method="LogAfter" pointcut-ref="printLog" />
   </aop:aspect>
  </aop:config>
</beans> 
timeHandler는 HelloWorld 인터페이스 print로만 시작하는 방법, logHandler는 HelloWorld 인터페이스 do로만 시작하는 방법
3. CGLIB를 사용하여 프록시 생성
앞에서 말했듯이 Spring은 동적 프록시나 CGLIB 생성 프록시를 사용하는 것이 규칙적이다. 높은 버전의 Spring은 동적 프록시를 사용할지 CGLIB 생성 프록시 내용을 사용할지 자동으로 선택한다. 물론 우리는 CGLIB 생성 프록시를 강제로 사용할 수 있다. 바로 에'proxy-target-class'속성이 있는데 이 속성 값이true로 설정되면 클래스 기반 프록시가 작용할 것이다.만약proxy-target-class가false로 설정되거나 이 속성이 생략된다면 인터페이스 기반 에이전트가 작용할 것입니다
이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.

좋은 웹페이지 즐겨찾기