spring 非xml配置 非@Aspect 註解 使用aop切面程式設計 方便深入學習aop原始碼
阿新 • • 發佈:2018-11-11
使用maven專案,實現基於純java的類程式碼實現spring的aop功能,不用xml配置,不用aop註解實現aop,直接使用類的java程式碼實現,直接執行main方法,看到aop結果輸出
//pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.dddd</groupId> <artifactId>spring</artifactId> <version>1.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <spring.version>4.3.3.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.7</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.10</version> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build> </project>
//logback.xml 配置日誌,顯示所有spring內部日誌,通過日誌,檢視執行流程 <?xml version="1.0" encoding="UTF-8"?> <configuration debug="false" scan="false" scanPeriod="30 second"> <property name="MAXHISTORY" value="100"/> <timestamp key="DATETIME" datePattern="yyyy-MM-dd HH:mm:ss"/> <!-- 控制檯列印 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="utf-8"> <pattern>[%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n </pattern> </encoder> </appender> <root level="ALL"> <appender-ref ref="STDOUT"/> </root> </configuration>
//ServInter.java 介面類
package com.dddd.aop;
public interface ServInter {
public void say();
}
//MyService.java 介面實現類,被代理物件 package com.dddd.aop; import org.springframework.stereotype.Service; @Service public class MyService implements ServInter { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void say() { System.out.println("MyService say:" + name); } }
//MyBeforeAop.java aop前置通知處理類
package com.dddd.aop;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class MyBeforeAop implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("before aop ["+method.getName()+"] do sth...................");
}
}
上面三個類檔案是準備工作,下面寫一個main方法,實現spring的aop,上面的註解是為了,方便快速新增bean到spring中
//Test.java
public class Test {
public static void main(String[] args) {
//aop 使用ProxyFactoryBean
//AnnotationConfigApplicationContext可以換成ApplicationContext 介面
//使用支援註解的容器,掃描包,直接新增bean
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("com.dddd.aop");
ServInter servInter = ac.getBean(ServInter.class);
MyBeforeAop myAop = (MyBeforeAop) ac.getBean("myBeforeAop");
//代理物件,aop的關鍵類就是這個代理類,會自動識別,如果是介面代理,使用jdk的代理,其他使用cglib代理
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setBeanFactory(ac.getBeanFactory());
proxyFactoryBean.setInterceptorNames("myBeforeAop");
proxyFactoryBean.setInterfaces(ServInter.class);
proxyFactoryBean.setTarget(servInter);
//這裡注意下面物件獲取,不能直接使用上面的從getBean獲取的,要不然沒有aop效果
//aop的本質就是使用一個代理類(理解為包裹了原來的bean的一個代理bean)
//呼叫的代理類產生的你需要的bean的方法,代理類才能知道你要呼叫的是哪個類的哪個方法,以實現代理
//直接呼叫bean的方法,代理類是無法知道的,所有就aop不了了
ServInter servInterProxy = (ServInter) proxyFactoryBean.getObject();
servInterProxy.say();
//aop2 使用ProxyFactory
ac = new AnnotationConfigApplicationContext("com.dddd.aop");
servInter = ac.getBean(ServInter.class);
myAop = (MyBeforeAop) ac.getBean("myBeforeAop");
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(servInter);
proxyFactory.addAdvice(myAop);
servInterProxy = (ServInter) proxyFactory.getProxy();
servInterProxy.say();
}
}
其他幾種aop方式類似, 列出介面名
org.springframework.aop.MethodBeforeAdvice 前置
org.springframework.aop.AfterReturningAdvice 後置
org.springframework.aop.ThrowsAdvice 異常攔截
org.aopalliance.intercept.MethodInterceptor 環繞