简介
Spring中AOP的实现就是通过动态代理来实现的。
重要概念
Aspect(切面):对象操作过程中的截面。如权限检查、日志、事务处理等。
Join Point(连接点):程序运行中的某个阶段点。如某个方法调用,异常抛出等。
Advice(处理逻辑):某个连接点所采用的处理逻辑。
PointCut(切点):一系列连接点的集合,它指明Advice在什么时候被触发。
实现
JDK实现
spring实现
<bean id="myPointcutAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="MyInterceptor" />
</property>
<property name="patterns">
<list>
<value>.*save.*</value>
<value>.*do.*</value>
</list>
</property>
</bean>
上面我们针对MyInterceptor设定了一个基于方法名的触发条件,也就是说,当目标类的指定方法运行时,MyInterceptor即被触发。
最后,我们还需要定义一个Spring AOP ProxyFactory, 加载执行AOP组件,并且需要将Advice通过IOC的方式注入到接口以及实现类。
对应的配置文件应如下配置从而实现这些内容:
<bean id="myAOPProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>test.aop.spring.DomainObjDAO</value>
</property>
<property name="target">
<ref local="impl" />
</property>
<property name="interceptorNames">
<value>myPointcutAdvisor</value>
</property>
</bean>
测试
ApplicationContext ctx=new FileSystemXmlApplicationContext("test/Bean.xml");
test = (DomainObjDAO) ctx.getBean("myAOPProxy");
ProxyFactoryBean 源码
import java.net.SocketAddress;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* {@link FactoryBean} that creates a {@link Proxy java.net.Proxy}.
*
* @author Arjen Poutsma
* @since 3.0.4
* @see FactoryBean
* @see Proxy
*/
public class ProxyFactoryBean implements FactoryBean<Proxy>, InitializingBean {
private Proxy.Type type = Proxy.Type.HTTP;
private String hostname;
private int port = -1;
private Proxy proxy;
/**
* 设置代理类型. 默认设置成 {@link java.net.Proxy.Type#HTTP}.
*/
public void setType(Proxy.Type type) {
this.type = type;
}
/**
* 设置代理主机名称
*/
public void setHostname(String hostname) {
this.hostname = hostname;
}
/**
* 设置代理接口
*/
public void setPort(int port) {
this.port = port;
}
//重写InitializingBean
@Override
public void afterPropertiesSet() throws IllegalArgumentException {
Assert.notNull(type, "'type' must not be null");
Assert.hasLength(hostname, "'hostname' must not be empty");
Assert.isTrue(port >= 0 && port <= 65535, "'port' out of range: " + port);
SocketAddress socketAddress = new InetSocketAddress(hostname, port);
this.proxy = new Proxy(type, socketAddress);
}
//重写factoryBean
@Override
public Proxy getObject() {
return proxy;
}
@Override
public Class<?> getObjectType() {
return Proxy.class;
}
@Override
public boolean isSingleton() {
return true;
}