aop示例:demo1
package com.jt.demo1.service;
public interface UserService {
void addUser();
}
package com.jt.demo1.service;
import org.springframework.stereotype.Service;
@Service
public class UserServiceIml implements UserService{
/**
* 业务:要求尽可能松耦合
* 分析: 1.UserService是业务处理类,其中addUser方法完成用户新增
* 2.其中事务的代码与业务代码紧紧的耦合在一起
* 3.如果事务的机制发生了变化,则所有的代码都将改变,耦合性高
* 当前业务的耦合性太高了!!!
* 4.代码复用性差
*/
@Override
public void addUser() {
System.out.println("事物开始");
System.out.println("新增用户陈宫!!!");
System.out.println("陈宫很开心!!!");
}
}
package com.jt.demo1.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.jt.demo1")
public class SpringConfig {
}
package com.jt.demo1.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//当前类是工具API,目的是获取代理对象
public class JDKProxy {
/**参数说明:
* ClassLoader loader 类加载器,将class加载到java运行机制中
* Class<?>[] interfaces 被代理者的接口数组,java可以多实现
* InvocationHandler h 将代理对象扩展的内容写到处理器中
* 注意事项: JDK代理必须要求 "被代理者"要么有接口(本身就是接口),要么实现接口(实现类)
* @param target
* @return
*/
public static Object getProxy(Object target){
//1.获取目标对象的类加载器
ClassLoader loader = target.getClass().getClassLoader();
//2.获取接口数组
Class<?>[] interfaces = target.getClass().getInterfaces();
//3.获取处理器对象
InvocationHandler handler = getInvocationHandler(target);
//4.利用动态代理获取对象
return Proxy.newProxyInstance(loader,interfaces,handler);
}
public static InvocationHandler getInvocationHandler(Object target){
//当代理对象执行业务操作时,通过InvocationHandler进行业务的扩展
return new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("事务开始");
//调用 让目标方法执行 target:目标对象!!! 其他都是固定写法!
Object result = method.invoke(target, args);
System.out.println("事务提交");
return result;
}
};
}
}
package com.jt.demo1.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy {
public static Object getObject(Object target){
//创建增强器对象
Enhancer enhancer = new Enhancer();
//设置父级
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(getMethodInterceptor());
return enhancer.create();
}
public static MethodInterceptor getMethodInterceptor(){
return new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("数据库事务开始");
Object proxy = methodProxy.invokeSuper(o,objects);
System.out.println("数据库事务提交");
return proxy;
}
};
}
}
package com.jt.demo1.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TimeProxy {
public static Object getProxy(Object target){
ClassLoader loader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long staTime = System.currentTimeMillis();
Object result = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println((endTime-staTime)+"毫秒");
return result;
}
};
return Proxy.newProxyInstance(loader, interfaces, handler);
}
}
package com.jt.demo1;
import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.proxy.CglibProxy;
import com.jt.demo1.proxy.JDKProxy;
import com.jt.demo1.proxy.TimeProxy;
import com.jt.demo1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestTx {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
//1.获取目标对象 userServiceIml实现类的对象
UserService target = context.getBean(UserService.class);
//2.获取代理对象 因为代理对象和被代理对象实现了同一个接口,因此可以进行类型的强制转换
//JDK动态代理测试
// UserService proxy = (UserService)JDKProxy.getProxy(target);
//JDK动态代理测试计时
// UserService proxy = (UserService) TimeProxy.getProxy(target);
//Cglib动态代理测试
UserService proxy = (UserService)CglibProxy.getObject(target);
proxy.addUser();
}
}
AOP示例:demo2
package com.jt.demo2.service;
public interface UserService {
void addUser();
String findName();
}
package com.jt.demo2.service;
import com.jt.demo2.anno.TX;
import org.springframework.stereotype.Service;
@Service
public class UserServiceIml implements UserService {
/**
* 业务:要求尽可能松耦合
* 分析: 1.UserService是业务处理类,其中addUser方法完成用户新增
* 2.其中事务的代码与业务代码紧紧的耦合在一起
* 3.如果事务的机制发生了变化,则所有的代码都将改变,耦合性高
* 当前业务的耦合性太高了!!!
* 4.代码复用性差
*/
//注解标识方式
@TX //满足表达式,扩展方法得到展现,不满足表达式,扩展方法无法显示
@Override
public void addUser() {
System.out.println("新增用户陈宫!!!");
System.out.println("陈宫很开心!!!");
// int a = 1/0;
}
@Override
@TX
public String findName() {
System.out.println("中秋快乐");
// int a = 1/0;
return "春节愉快";
}
}
package com.jt.demo2.service;
import com.jt.demo2.anno.TX;
import org.springframework.stereotype.Component;
@Component //key:userCommon
public class UserCommon {
@TX
public void say(){
System.out.println("测试代理机制");
}
}
package com.jt.demo2.anno;
//本类为自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) //注解对方法有效
@Retention(RetentionPolicy.RUNTIME) //运行期有效
public @interface TX {
}
package com.jt.demo2.aop;
//本类用于测试通知方法
//AOP 面向切面编程 1年开发
//知识铺垫: 切面 = 动态代理 + 方法的扩展 后期被AOP API封装
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component //将这个类交给spring容器管理
@Aspect //标识当前类是一个切面
@Order(value = 1) //数字越小,越先执行
public class TxAspect {
//编码: 切面 = 切入点表达式 + 通知方法
//切入点表达式:为谁创建代理对象!!!
// @Pointcut("bean(userServiceIml)") //标识切入点表达式 识别一个类
// @Pointcut("within(com.jt.demo2..service.*)") //识别多个类
// @Pointcut("execution(void com.jt.demo2.service.UserServiceIml.addUser())")
@Pointcut("@annotation(com.jt.demo2.anno.TX)")
public void pointCut(){
}
//通知方法:对原有方法的扩展
//1.前置通知:在目标方法运行前,执行本方法
@Before("pointCut()") //通知注解
public void before(JoinPoint joinPoint){
//1.获取目标对象的类型
Class targetClass = joinPoint.getTarget().getClass();
//2.获取目标对象的名称
String targetName = joinPoint.getSignature().getDeclaringTypeName();
//3.获取目标方法的名称
String methodName = joinPoint.getSignature().getName();
//4.获取目标方法的参数
Object[] args = joinPoint.getArgs();
System.out.println("目标对象类型:"+targetClass);
System.out.println("目标对象名称:"+targetName);
System.out.println("目标方法名称:"+methodName);
System.out.println("目标方法参数:"+ Arrays.toString(args));
}
//2.后置通知:目标方法正常运行后,执行本方法
/**记录目标方法的返回值结果
* returning: 后置通知获取返回值的属性*/
@AfterReturning(value = "pointCut()",returning = "result")
public void afterReturning(Object result){
System.out.println("方法的返回值:"+result);
}
//3.抛出异常通知:如果目标方法运行时抛出异常,执行本方法
/**说明:如果程序执行抛出异常,则可以由异常通知进行记录
* throwing:抛出异常的属性
*/
@AfterThrowing(value = "pointCut()",throwing = "exception")
public void afterThrowing(Exception exception){
//exception.printStackTrace();
System.out.println("异常信息:"+exception.getMessage());
}
//4.最终通知:不管目标方法是否正常执行,都会执行本方法
@After("pointCut()")
public void after(){
System.out.println("我是最后通牒");
}
/*5.环绕通知:
* 说明:1.前四大通知类型不能控制目标方法的运行,所以使用时一般记录程序的运行状态
* 2.在目标方法执行前后都要运行,只有环绕通知才可以控制目标方法是否运行,使用最多的通知方法
* 注意事项:环绕通知中必须添加参数,且参数必须位于第一位
* 用法:
* Proceed with the next advice or target method invocation
* 1.如果有下一个通知,则执行下一个通知
* 2.如果没有下一个通知,则执行目标方法*/
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知开始");
Object result = joinPoint.proceed();
System.out.println("环绕通知结束");
return result;
}
}
package com.jt.demo2.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(value = 2)
public class Aspect2 {
@Around("@annotation(com.jt.demo2.anno.TX)")
public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
System.out.println("环绕通知开始2");
Object result = joinPoint.proceed();
System.out.println("环绕通知结束2");
return result;
}
}
package com.jt.demo2.config;
//本类为配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.jt.demo2")
@EnableAspectJAutoProxy
//强制使用Cglib动态代理
//@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringConfig {
}
package com.jt.demo2;
import com.jt.demo2.config.SpringConfig;
import com.jt.demo2.service.UserCommon;
import com.jt.demo2.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TsetTx {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
//看上去:是目标对象 AOP:内部已经封装动态代理规则
//实际上:已经被AOP封装,是一个代理对象
UserService user = context.getBean(UserService.class);
System.out.println(user.getClass());
//代理机制,可以扩展方法
// user.addUser();
user.findName();
//测试cglib代理模式
UserCommon userCommon = context.getBean(UserCommon.class);
System.out.println(userCommon.getClass());
userCommon.say();
}
}
AOP示例:demo3
package com.jt.demo3.service;
public interface UserService {
void addUser();
}
package com.jt.demo3.service;
import org.springframework.stereotype.Service;
@Service
public class UserServiceIml implements UserService {
@Override
public void addUser() {
System.out.println("三英战吕布!!!");
int a = 1/0;
}
}
package com.jt.demo3.aop;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.logging.SocketHandler;
@Component
@Aspect //标识当前类是切面类
public class DemoAspect {
//作用:如果匹配了切入点表达式,为其创建代理对象 jdk动态代理
@Around("bean(userServiceIml)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
//获取数据信息
Class<?> targetClass = joinPoint.getTarget().getClass();
String typeName = joinPoint.getSignature().getDeclaringTypeName();
String name = joinPoint.getSignature().getName();
System.out.println("目标对象的类型:"+targetClass);
System.out.println("目标对象的名称:"+typeName);
System.out.println("目标方法的名称:"+name);
return result;
}
/*@AfterThrowing("execution(返回值类型 包名.类名.方法名(参数列表))")
* ps:1.'*'号表示所有类型
* 2.'..'表示不做限制*/
@AfterThrowing("execution(* com.jt.demo3.service..*.*(..))")
public void afterThrowing(){
System.out.println("关羽窜稀了!!!");
}
}
package com.jt.demo3.config;
//本类为配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.jt.demo3")
@EnableAspectJAutoProxy
public class SpringConfig {
}
package com.jt.demo3;
import com.jt.demo3.config.SpringConfig;
import com.jt.demo3.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestDemo {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
UserService user = context.getBean(UserService.class);
user.addUser();
}
}