지난 며칠 동안 SpringAop을 공부하다가 인터넷에서 몇 가지 정보를 찾았습니다. 이 링크는 원본 링크입니다. (Aspect Oriented 프로그래밍), 즉 관점 지향 프로그래밍은 OOP(객체 지향 프로그래밍, 객체 지향 프로그래밍)의 보완이자 개선이라고 할 수 있습니다. OOP는 캡슐화, 상속, 다형성과 같은 개념을 도입하여 공개 동작 모음을 시뮬레이션하는 데 사용되는 개체 계층 구조를 설정합니다. 그러나 OOP를 사용하면 개발자가 수직적 관계를 정의할 수 있지만 로깅 기능과 같은 수평적 관계를 정의하는 데는 적합하지 않습니다. 로깅 코드는 종종 모든 개체 계층에 걸쳐 수평으로 분산되며 해당 개체의 핵심 기능과 아무런 관련이 없습니다. 보안, 예외 처리, 관련 없는 코드 등 다른 유형의 코드에도 마찬가지입니다. OOP 디자인에서는 많은 양의 코드가 중복되어 다양한 모듈을 재사용하는 데 도움이 되지 않습니다.
AOP 기술은 그와 정반대인데, 캡슐화된 객체의 내부를 분해하고 여러 클래스에 영향을 미치는 공개 행위를 재사용 가능한 모듈로 캡슐화하고 이름을 "Aspect"로 지정하는 기술을 사용합니다. 측면이다. 소위 "측면"은 비즈니스와 관련이 없지만 비즈니스 모듈에 의해 공동으로 호출되는 단순히 캡슐화된 논리 또는 책임입니다. 이를 통해 시스템에서 코드 중복을 줄이고, 모듈 간의 결합을 줄이고, 미래의 운용성과 유지보수성. "크로스 커팅" 기술을 사용하여 AOP는 소프트웨어 시스템을
핵심 관심사와
크로스 커팅 관심사의 두 부분으로 나눕니다. 비즈니스 처리의 주요 프로세스가 핵심 관심사이고, 그것과 관련이 거의 없는 부분이 교차 관심사입니다. 크로스커팅 관심사의 특징 중 하나는 핵심 관심사의 여러 곳에서 발생하는 경우가 많고, 권한 인증, 로그, 사물 등 기본적으로 장소가 유사하다는 점이다. AOP의 역할은 시스템의 다양한 관심사를 분리하여 핵심 관심사와 교차 관심사를 분리하는 것입니다.
AOP 핵심 개념
1. 교차 우려
어떤 방식으로 차단해야 하며, 차단 후 어떻게 처리해야 할까요? 이러한 우려 사항을 Aspect라고 합니다. 객체 특성의 추상화이고, Aspect는 교차 관심의 추상화입니다
3. Joinpoint(조인포인트)
가로채기된 지점, Spring에서는 메서드 유형의 연결 지점만 지원하므로 Spring에서는 조인포인트를 가로채는 메서드를 말합니다. 실제로 연결 지점은 필드나 생성자일 수도 있습니다.
4. 포인트컷(pointcut)
연결 지점 가로채기의 정의
5. 조언(advice)
소위 알림이 되는 코드를 말합니다. 알림은 사전, 사후, 예외, 최종 및 주변 알림의 5가지 범주로 나누어집니다. 대상 개체
프록시의 대상 개체
7.
대상 개체에 측면을 적용하고 프록시 개체를 생성하는 프로세스
8. 소개
코드를 수정하지 않고도 소개는
런타임또는 필드
중에 클래스에 일부 메서드를 동적으로 추가할 수 있습니다.
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입니다. 먼저 설명하겠습니다. Spring AOP를 사용하려면 코드를 성공적으로 실행하려면 Spring에서 개발자에게 제공하는 jar 패키지만 사용하는 것만으로는 충분하지 않습니다. 온라인에서 두 개의 jar를 추가로 다운로드하세요. 패키지:
1, aopalliance.jar
2, Aspectjweaver .jar
Spring 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>두 가지 인터페이스 구현 클래스를 정의합니다.
1 public interface HelloWorld 2 { 3 void printHelloWorld(); 4 void doPrint(); 5 }
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 ; } }다음은 세 가지 클래스로 간단한 Spring AOP를 구현할 수 있습니다. aop.xml의 구성을 살펴보세요
public class TimeHandler { public void printTime() { System.out.println("CurrentTime = " + System.currentTimeMillis()); } }이를 호출하는 기본 함수를 작성하세요.
<?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>실행 결과는 다음과 같습니다.
CurrentTime = 1446129611993Enter HelloWorldImpl1.printHelloWorld() CurrentTime = 1446129611993CurrentTime = 1446129611994Enter HelloWorldImpl1.doPrint() CurrentTime = 1446129611994CurrentTime = 1446129611994Enter HelloWorldImpl2.printHelloWorld() CurrentTime = 1446129611994CurrentTime = 1446129611994Enter 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"); } }
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" /> <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、我只想织入接口中的某些方法
修改一下pointcut的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生成代理,那就是5f4edcee1f0c5735c643ff3ca537e591里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用。
위 내용은 Java의 SpringAop에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!