实现原理:
引起增强完成功能:
引入增强是一种比较特殊的增强类型,不是在目标方法周围植入增强,而是为目标类创建新的方法和属性所以引入增强的连接点是类级别的,而非方法级别
通过引入增强,我们可以为目标类添加一个接口的实现(即目标类可能为实现的接口),通过引入增强代理实现新的功能
例如实现:一个开关控制利用一个开关控制是否进行性能监控
1. 定义开关监控接口 Monitor
2. 定义实现类ControllablePerformanceMonitor继承DelegatingIntroductionInterceptor并实现接口Monitor
3. 定义ThreadLocal变量用于存储开关的值
4. 重写函数 invoke 并根据开关的值来决定是否调用嵌入的性能监控逻辑
5. 配置XML
定义接口类
package com.advice;
import com.smart.domain.User;
import java.sql.SQLException;
/**
* @author Duoduo
* @version 1.0
* @date 2017/4/22 18:58
*/
public interface IUserDao {
int addUser(User user);
int updateUser(User user);
void deleteUser(User user);
void removeUser(User user) throws SQLException;
}
接口实现类
package com.advice;
import com.smart.domain.User;
import java.sql.SQLException;
/**
* @author Duoduo
* @version 1.0
* @date 2017/4/22 19:00
*/
public class UserDaoImpl implements IUserDao {
@Override
public int addUser(User user) {
System.out.println("Add user");
return 0;
}
@Override
public int updateUser(User user) {
System.out.println("Update user");
return 0;
}
@Override
public void deleteUser(User user) {
//throw new RuntimeException("exception test");
}
@Override
public void removeUser(User user) throws SQLException {
//throw new SQLException("SQLException Test");
}
}
定义新增开关功能的接口
package com.advice;
/**
* @author Duoduo
* @version 1.0
* @date 2017/4/23 11:20
*/
public interface Monitor {
void setMonitorActive(boolean active);
}
定义引入增强类
package com.advice;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
/**
* 引入增强:
* 是一种比较特殊的增强类型,不是在目标方法周围植入增强,而是为目标类创建新的方法和属性
* 所以引入增强的连接点是类级别的,而非方法级别
*
* 通过引入增强,我们可以为目标类添加一个接口的实现(即目标类可能为实现的接口),通过引入增强代理实现新的功能
*
* @author Duoduo
* @version 1.0
* @date 2017/4/23 11:21
*/
public class ControllablePerformanceMonitor extends DelegatingIntroductionInterceptor implements Monitor {
//当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
//所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
private ThreadLocal<Boolean> monitorStatus = new ThreadLocal<Boolean>();
@Override
public void setMonitorActive(boolean active) {
monitorStatus.set(active);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object object = null;
Boolean active = monitorStatus.get();
if (active != null && active) {
System.out.println("Performance monitor start ..... for method "+ mi.getMethod().getName());
object = super.invoke(mi);
System.out.println("Performance monitor end ..... for method "+ mi.getMethod().getName());
}else{
object = super.invoke(mi);
}
return object;
}
}
Spring XML 配置
特别注意:代理工厂是 ProxyFactoryBean 不是 ProxyFactory
<bean id="performanceMonitor" class="com.advice.ControllablePerformanceMonitor"/>
<bean id="userDaoProxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interfaces="com.advice.Monitor"
p:target-ref="userDaoImpl"
p:interceptorNames="performanceMonitor"
p:proxyTargetClass="true"/>
Junit测试类
@Test
public void introductionTest(){
System.out.println("************ introductionTest start *************");
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-another-context.xml");
//获取代理类
UserDaoImpl userDaoProxyFactory = (UserDaoImpl)context.getBean("userDaoProxyFactory");
System.out.println("========= set monitor true ============");
Monitor monitor = (Monitor)userDaoProxyFactory;
monitor.setMonitorActive(true);
userDaoProxyFactory.addUser(user);
System.out.println("========= set monitor false ============");
monitor.setMonitorActive(false);
userDaoProxyFactory.addUser(user);
System.out.println("************ introductionTest end *************");
}
测试结果
========= set monitor true ============
Performance monitor start ..... for method addUser
Add user
Performance monitor end ..... for method addUser
========= set monitor false ============
Performance monitor start ..... for method setMonitorActive
Performance monitor end ..... for method setMonitorActive
Add user
************ introductionTest end *************
************ addUserAdivceTest ************