关键词
切面(Aspect):切面是要实现的交叉功能。最常见的例子是日志记录。
连接点(Jointpoint)连接点是应用程序执行过程中插入切面的地点。这个地点可以是:方法调用;异常抛出;字段的修改。
通知 (Advice)通知是切面的实际实现。它通知应用系统新的行为。在日志例子中,日志通知包含了实现日志功能的代码。通知在连接点插入到系统中。
切入点(Pointcut)切入点定义了通知应该应用在哪些连接点上。通常通过指定类名和方法名,或者匹配类名和方法名式样的正则表达式来制定切入点。
引入(Introduction)引入允许在不改变已存在类的情况下为其添加新方法和属性,给他们新的行为和状态。
目标对象(Target)被通知的对象。但目标对象对应用在其上的通知浑然不觉。
代理(Proxy)代理是将通知应用到目标对象后创建的对象。对于客户来说,目标对象(应用AOP之前的对象)和代理对象是一样的。应用系统的其他部分不用为了支持代理对象而作出改变。
Spring的AOP实现
♦用JAVA编写通知
♦运行时通知对象
代理Bean在运行期被创建。有两种创建方式:
目标对象接口实现 | 实现方式 |
实现了一个或多个接口 | Spring使用JDK的java.lang.reflect.Proxy类创建代理,这个类让Spring动态产生一个新类。该类实现了所需要的接口,织入了通知,并且代理对目标对象的所有请求。 |
没有实现任何接口 | Spring使用CGLIB库生生目标对象的子类,在创建子类时,Spring将通知织入,并将对目标对象的调用委托给这个子类。 |
使用第二种方式时需要注意两点:
1)对接口创建代理优于对类创建代理,这样会产生更加松耦合的系统。
2)标记为final的方法不能被通知。Spring为目标类产生子类,任何需要被通知的方法都要被复写,将通知织入。final方法无法作到这一点。
♦实现了AOP联盟接口
♦只支持方法连接点
这与其他AOP框架不同,如AspectJ和JBoss,他们还提供了属性接入点。
一个简单的AOP实现
package
spring;
// 目标对象要实现的接口
public interface ICustomer ... {
public abstract void buy();
}
pubilc class ICustomerImpl implements ICustomer ... {
private String name;
public setName(String name)...{
this.name = name;
}
package spring;
//目标对象类
public class ICustomerImpl implements ICustomer...{
private String name;
public void setName(String name)...{
this.name = name;
}
public String getName()...{
return this.name;
}
public void buy()...{
System.out.println("buy something");
}
}
//消息类
package spring;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class WelcomeAdvice implements MethodBeforeAdvice...{
public void before(Method m,Object[]args,Object target)...{
ICustomerImpl c = (ICustomerImpl)target;
System.out.println("Welcome "+c.getName());
}
}
//配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="customerTarget"
class="spring.ICustomerImpl">
<property name="name">
<value>moron</value>
</property>
</bean>
<bean id="welcomeAdvice"
class="spring.WelcomeAdvice"></bean>
<bean id="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>spring.ICustomer</value>
</property>
<property name="target">
<ref bean="customerTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>welcomeAdvice</value>
</list>
</property>
</bean>
</beans>
//测试类
package spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAdvice ...{
/** *//**
* @param args
*/
public static void main(String[] args) ...{
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ICustomer customer = (ICustomer)context.getBean("proxy");
customer.buy();
}
}
// 目标对象要实现的接口
public interface ICustomer ... {
public abstract void buy();
}
pubilc class ICustomerImpl implements ICustomer ... {
private String name;
public setName(String name)...{
this.name = name;
}
package spring;
//目标对象类
public class ICustomerImpl implements ICustomer...{
private String name;
public void setName(String name)...{
this.name = name;
}
public String getName()...{
return this.name;
}
public void buy()...{
System.out.println("buy something");
}
}
//消息类
package spring;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class WelcomeAdvice implements MethodBeforeAdvice...{
public void before(Method m,Object[]args,Object target)...{
ICustomerImpl c = (ICustomerImpl)target;
System.out.println("Welcome "+c.getName());
}
}
//配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="customerTarget"
class="spring.ICustomerImpl">
<property name="name">
<value>moron</value>
</property>
</bean>
<bean id="welcomeAdvice"
class="spring.WelcomeAdvice"></bean>
<bean id="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>spring.ICustomer</value>
</property>
<property name="target">
<ref bean="customerTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>welcomeAdvice</value>
</list>
</property>
</bean>
</beans>
//测试类
package spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAdvice ...{
/** *//**
* @param args
*/
public static void main(String[] args) ...{
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ICustomer customer = (ICustomer)context.getBean("proxy");
customer.buy();
}
}