栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

AOP面向切面编程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

AOP面向切面编程

1.概念(5)

AOP:面向切面编程AOP思想
Aspect 切面:功能模块切入多个类中

@Aspect:有此注解就一定要托管@Component

Join Point 连接点:预测表达式Pointcut 切入点:新功能切入的点Advice 行为:切入点上的行为,即新功能Target object 目标类:待增强功能的类AOP proxy 代理类:目标类+切面生成的一个新类,实际调用的也是该类中的方法
使用前导入jar包


	org.aspectj
    aspectjweaver
    1.9.8

2.AOP使用

代理类(配置类) @EnableAspectJAutoProxy

@EnableAspectJAutoProxy:自动检测@Aspect	
	-->相当于代理类中扫描切面类
--------------------------------------------------------------
@Configuration
@ComponentScan(basePackages = "com.yc.bean")
@EnableAspectJAutoProxy
public class AppConfig {
    @Bean
    public Random r() {
        return new Random();
    }
}

切面类 @Aspect

1.@Aspect:表明这是一个切面类
2.@Pointcut("execution(* transfer(..))"):切入点表达式(5.4.3)
	-->在方法上
	-->execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
	-->0或1个修饰符,返回值类型,0或1个声明类型模式,方法模式(参数模式),抛出异常模式
3.@Before/@Around/..:切入点位置
	-->@Before:前置增强
			默认顺序根据方法名,@Order(1)可以设置切面类的优先级,也可以实现接口Ordered
	-->@Around:环绕增强(方法有一部分先执行,一部分后执行)
			高优先级进去先,后出来
			返回值Object,参数ProceedingJoinPoint
--------------------------------------------------------------
@Component
@Aspect
public class MyAspect {
    @Pointcut("execution(* com.yc.bean.Container.add(..))")
    private void a() {  }

    @Before("com.yc.bean.MyAspect.a()")//切入点位置
    public void log(JoinPoint jp) {//JoinPoint实际是一个接口,该对象在调用时以di方式注入
        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = df.format(date);
        System.out.println("当前执行的时间:" + time);

        Object target = jp.getTarget();//取出目标类
        Object proxy = jp.getThis();//取出代理类
        Object[] params = jp.getArgs();//取出参数
    }

    @Around("a()")
    public Object runtime(ProceedingJoinPoint pjp) {//ProceedingJoinPoint环绕增强时使用,必须要该参数
        long starttime = System.currentTimeMillis();
        Object returnValue = null;
        try {
            returnValue = pjp.proceed();//运行该连接点
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        long endtime = System.currentTimeMillis();
        System.out.println("程序运行时间:" + (endtime - starttime));
        return returnValue;//必须要用该返回值(连接点方法的返回值)
    }
}
3.合并切入点
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} 

@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {} 

@Pointcut("anyPublicOperation() && inTrading()")//某包下的所有public方法
private void tradingOperation() {} 
4.代理机制

静态代理:只能代理一个确定的类动态代理:任意的目标类都可以代理JDK 面向接口

1.回调器:实现InvocationHandler接口,定义目标target类,目标类是一个接口实现类
	public class CustomInvocationHandler implements InvocationHandler {
	    private Object target;//目标类引用
	
	    public CustomInvocationHandler(Object target) {this.target = target;}
	
	    //生成代理对象,代理接口中所有方法
	    //(类加载器/字节码加载器,目标类所有接口,激活时的回调处理器)
	    public Object createInstance() {
	        return Proxy.newProxyInstance(CustomInvocationHandler.class.getClassLoader(),
	                target.getClass().getInterfaces(), this);
	    }
	
	    //实现一个接口  对目标类生成代理对象
	    //感知到客户端调用被代理的方法,自动回调invoke(),激活对应方法
	    @Override
	    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	        if (method.getName().equalsIgnoreCase("sayHello")) {
	            System.out.println("Before invocation");//升级成切入点表达式
	        }
	
	        Object retVal = method.invoke(target, args);
	        //相当于调用了目标类的sayHello()   target.method(args)
	        System.out.println("After invocation");
	        return retVal;
	    }
	}
2.Hello接口
	public interface Hello {
	    public void sayHello(String name);
	    public void bye();
	}
3.HelloImpl接口实现类
	public class HelloImpl implements Hello {
	    @Override
	    public void sayHello(String name) {
	        System.out.println("Hello:" + name);
	    }
	    @Override
	    public void bye() {
	        System.out.println("bye");
	    }
	}
4.测试类
	public class TestMain {
	    public static void main(String[] args) {
	        //保存生成的字节码文件 com.sun... -->为源码解读做准备
	        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
	
	        CustomInvocationHandler handler = new CustomInvocationHandler(new HelloImpl());
	
	        //生成代理类对象 $Proxy -->生成字节码的时机:运行期由jdk动态代理来生成字节码,编译块,运行慢(动态代理机制)
	        Hello proxy = (Hello) handler.createInstance();
	        //自动激活invoke
	        proxy.sayHello("hhhh");//$proxy0.sayHello()
	        proxy.bye();
	    }
	}

JDKProxy源码解读CGLIB 面向继承

1.使用前导入jar包
	
		
		cglib
		cglib
		3.3.0
	
2.方法拦截器:实现MethodInterceptor接口,定义目标target类
	public class MyInterceptor implements MethodInterceptor {
	    //生成代理对象
	    public Enhancer enhancer = new Enhancer();
	    //目标对象
	    private Object target;
	
	    public MyInterceptor(Object target) {this.target = target;}
	
	    //获取一个代理对象
	    public Object createInstance() {
	        enhancer.setSuperclass(this.target.getClass());
	        //设置被代理方法时的回调
	        enhancer.setCallback(this);
	        //生成代理对象
	        return enhancer.create();
	    }
	
	    //自动回调
	    @Override
	    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
	        if (method.getName().equalsIgnoreCase("sayHello")) {
	            System.out.println("Before invocation");//升级成切入点表达式
	        }
	        
	        //目标方法
	        Object result = methodProxy.invokeSuper(target, objects);
	        //相当于调用了目标类的sayHello()   target.method(args)
	        
	        System.out.println("After invocation");
	        return result;
	    }
	}
3.HelloImpl:未实现接口
	public class HelloImpl {
	    public void sayHello(String name) {
	        System.out.println("Hello:" + name);
	    }
	    public void bye() {
	        System.out.println("bye");
	    }
	}
4.测试类
	public class TestMain {
	    public static void main(String[] args) {
	        //保存生成的字节码文件 com.sun...
	        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
	
	        CustomInvocationHandler handler = new CustomInvocationHandler(new HelloImpl());
	
	        Hello proxy = (Hello) handler.createInstance();
	        proxy.sayHello("hhhh");
	        proxy.bye();
	    }
	}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/763342.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号