特点:
- 1.IOC 控制反转
- 2.AOP 面向切面编程
- 3.容器
- 4.组件化
- 5.一站式
- 6.非侵入式
IOC 注入 分set 注入和构造器注入 工厂模式+反射(反射如何实现看基础)
AOP 代理模式 (静态代理和动态代理) -- 解耦
静态代理
public class CalculatorStaticProxy implements Calculator {
//被代理目标对象传过来
private Calculator calculator;
public CalculatorStaticProxy(Calculator calculator) {
this.calculator = calculator;
}
@Override
public int add(int a, int b) {
System.out.println("日志开始");
//调用目标对象的方法实现核心业务
int result = calculator.add(a, b);
System.out.println(result);
System.out.println("日志结束");
return result;
}
}
动态代理 jdk代理(有接口,生成接口实现类) cglib代理(没有接口,生成子类代理对象)
package com.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
//目标对象
private Object object;
public ProxyFactory(Object object) {
this.object = object;
}
//创建方法返回代理对象
public Object getProxy() {
/**
* 有三个参数
*
*1.ClassLoader: 类加载器
* 2.Class[] interfaces: 目标对象实现的所有接口的class的数组
* 3.InvocationHandler: 设置代理对象实现目标对象方法的过程
*
*/
ClassLoader classLoader = object.getClass().getClassLoader();
Class<?>[] interfaces = object.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 需要重写目标对象
* @param args 对应方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用之前输出
System.out.println("动态代理" + method.getName());
//调用目标方法
Object invoke = method.invoke(object, args);
//调用之后输出
System.out.println("动态代理" + method.getName());
return invoke;
}
};
return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
1.横切关注点 2.通知(增强) 3.切面 4.目标 5.代理 6.连接点 7.切入点
package com.spring.anoaop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Aspect
@Component
public class LogAspect {
//设置切入点和通知类型
//切入点表达式 execution (public int 全类名 方法名 (参数))
//通知类型:
// 前置 @Before() (value = "切入点表达式")
@Before(value = "execution(public int com.spring.anoaop.CalculatorImpl.*(..))")
public void beforeMethod(){
System.out.println("输出前置通知");
}
// 返回 @AfterReturning
@AfterReturning(value = "execution(* com.spring.anoaop.CalculatorImpl.*(..))",returning = "result")
public void afterReturningMethod(JoinPoint joinPoint,Object result){
String name = joinPoint.getSignature().getName();
System.out.println("输出返回通知 方法名称"+name+"结果"+ result);
}
// 异常 @AfterThrowing
@AfterThrowing(value = "execution(* com.spring.anoaop.CalculatorImpl.*(..))",throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint,Throwable ex){
String name = joinPoint.getSignature().getName();
System.out.println("输出异常通知 方法名称"+name+"异常"+ex);
}
// 后置 @After()
@After(value = "execution(* com.spring.anoaop.CalculatorImpl.*(..))")
public void afterMethod(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("输出后置通知 方法名称"+name);
}
// 环绕 @Around()
@Around(value = "pointCut()")
public Object aroundMethod(ProceedingJoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
String s = Arrays.toString(args);
Object result =null;
try {
result= joinPoint.proceed();
System.out.println("环绕通知 执行方法返回通知");
}catch (Throwable throwable){
throwable.printStackTrace();
System.out.println("环绕通知 异常执行");
}finally {
System.out.println("输出环绕通知 最终通知");
}
return result;
}
//重用切入点表达式
@Pointcut(value = "execution(* com.spring.anoaop.CalculatorImpl.*(..))")
public void pointCut(){
}
}