1.介绍
Aspect Oriented Programming 面向切面编程,将程序中的相同业务逻辑进行横向隔离,将重复的业务逻辑抽取到一个独立的模块。、
- 连接点Joinpoint:程序执行过程中某个特定的节点
- 通知Advice:在目标类连接点上执行的代码,有around,before等类型
- 切点Pointcut:匹配连接点的断言,AOP通过其定位到连接点。
- 目标对象Target:通知所作用的目标类。
- 引介Introduction: 特殊的通知,为类添加属性和方法。动态地为业务类添加接口的实现逻辑。
- 切面Aspect: 对系统中的横切关注点逻辑进行模块化封装的AOP概念实体。
- 织入Weaving: 将通知添加到目标类具体连接点的过程,在编译,类加载,运行时完成,Spring动态代理织入,AspectJ编译期和类装载器织入。
- 代理Proxy:目标类被织入增强后产生的结果类,融合了原类和增强的逻辑。
2.实现机制
2.1 JDK动态代理
JDK代理只能为接口创建代理实例
- LoginService接口
public interface LoginService {
public void login();
}
- LoginServiceImpl
public class LoginServiceImpl implements LoginService{
@Override
public void login() {
System.out.println("Login");
}
}
- PerformHandler类
public class PerformHandler implements InvocationHandler {
private Object target;
public PerformHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强的方法
System.out.println("start");
//执行被代理类的原方法
Object invoke = method.invoke(target, args);
System.out.println("end");
return invoke;
}
}
- Test类
@Test
public void fun(){
LoginService loginService = new LoginServiceImpl();
//通过Proxy生成代理对象
PerformHandler performHandler = new PerformHandler(loginService);
loginService = (LoginService) Proxy.newProxyInstance(loginService.getClass().getClassLoader(),
loginService.getClass().getInterfaces(),performHandler);
loginService.login();
}
2.2 CGLib动态代理
CGLib动态代理为类创建实例 底层字节码技术 继承的方式实现
依靠Enhancer类创建代理实例 MethodInterceptor接口织入方法
- CglibProxy
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
//生成代理对象
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
//回调方法 拦截目标类所有方法调用
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("start");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("end");
return invoke;
}
}
- Test类
@Test
public void funG(){
CglibProxy cglibProxy = new CglibProxy();
//创建代理对象
LoginServiceImpl loginService = (LoginServiceImpl) cglibProxy.getProxy(LoginServiceImpl.class);
loginService.login();
}
3.实现方法
3.1 XML
- spring.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean name="loginService" class="service.LoginServiceImpl"></bean>
<bean name = "xmlAdvice" class="service.XmlAdvice"></bean>
<!-- Spring Aop-->
<aop:config>
<!-- 切点-->
<aop:pointcut id="pointcut" expression="execution(* service.LoginServiceImpl.*(..))"/>
<!-- 切面-->
<aop:aspect ref="xmlAdvice">
<!-- 前置-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<!-- 返回-->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut"></aop:after-returning>
<!-- 环绕-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
<!-- 异常-->
<aop:after-throwing method="afterException" pointcut-ref="pointcut"></aop:after-throwing>
<!-- 后置-->
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
</beans>
- Test类
@Test
public void funXml(){
ApplicationContext context = new ClassPathXmlApplicationContext("config/spring1.xml");
LoginService loginService = context.getBean("loginService", LoginService.class);
loginService.login();
}
3.2 注解
- Spring.xml 修改
<bean name="annoAdvice" class="service.AnnoAdvice"></bean>
<!-- 自动动态代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean name="loginService" class="service.LoginServiceImpl"></bean>
- AnnoAdvice类
@Aspect
public class AnnoAdvice {
//切点
@Pointcut("execution(* service.LoginServiceImpl.*(..))")
public void pointcut(){
}
@Before("pointcut()")
public void before(){
System.out.println("before");
}
//后置通知 异常不执行
@AfterReturning("pointcut()")
public void afterReturning(){
System.out.println("afterReturning");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable{
System.out.println("around start");
Object object = point.proceed();
System.out.println("around end");
return object;
}
@AfterThrowing("pointcut()")
public void afterException(){
System.out.println("Exception");
}
@After("pointcut()")
public void after(){
System.out.println("after");
}
}
标签:Object,System,loginService,AOP,println,public,out
From: https://www.cnblogs.com/lwx11111/p/17330784.html