使用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 环绕