• Spring IOC的理解


    • 控制反转(IOC):理论思想,传统java开发模式,对象是由使用者来进行管理,有了spring后,可以交给spring来帮我们进行管理,通过反射的方式生成对象。
    • 依赖注入(DI):把对应的属性的值注入到具体的对象中。
    • 容器:存储对象,使用map结构来存储,spring中一般存在三级缓存,singletonObjects存放完整的bean对象。
    • 切面编程(AOP):面向切面编程,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用 JDK 动态代理(创建接口实现类代理对象),如果是类采用CGLIB 方式实现动态代理(创建子类代理)。

    1.1 IOC 

     1.2 bean生命周期

    1.3 BeanFactory、FactoryBean

    1.4 循环依赖 

     

    1.5 三级缓存、暴露对象 

    1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    2. // 一级缓存
    3. private final Map singletonObjects = new ConcurrentHashMap(256);
    4. // 三级缓存
    5. private final Map> singletonFactories = new HashMap(16);
    6. // 二级缓存
    7. private final Map earlySingletonObjects = new HashMap(16);
    8. }
    1. /**
    2. * 函数式接口
    3. *
    4. * 可以将lambda表达式作为参数放到方法实参中
    5. * 在方法执行的时候并不会调用当前lambda表达式
    6. * 只有在调用getObject方法的时候才会去调用lambda表达式
    7. */
    8. @FunctionalInterface
    9. public interface ObjectFactory {
    10. T getObject() throws BeansException;
    11. }

    1.6 AOP

    JDK动态代理

    1. @Configuration
    2. @EnableAspectJAutoProxy
    3. @ComponentScan(basePackages = {"com.ww.spring5"})
    4. public class SpringConfig {
    5. }
    6. public interface UserDao {
    7. void add();
    8. }
    9. @Repository
    10. public class UserDaoImpl implements UserDao {
    11. @Autowired
    12. @Qualifier(value = "jdbcTemplate")
    13. JdbcTemplate jdbcTemplate;
    14. public JdbcTemplate getJdbcTemplate() {
    15. return jdbcTemplate;
    16. }
    17. @Override
    18. public void add() {
    19. System.out.println("do add......");
    20. }
    21. }
    22. public class UserDaoProxy implements InvocationHandler {
    23. private UserDaoImpl userDaoImpl;
    24. public UserDaoProxy(UserDaoImpl userDaoImpl) {
    25. this.userDaoImpl = userDaoImpl;
    26. }
    27. @Override
    28. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    29. System.out.println("before do method......");
    30. method.invoke(userDaoImpl);
    31. System.out.println("after do method......");
    32. return null;
    33. }
    34. }
    35. public class TestSpring {
    36. /**
    37. * jdk动态代理
    38. */
    39. @Test
    40. public void testProxy() {
    41. Class[] clazzs = {UserDao.class};
    42. UserDaoProxy userDaoProxy = new UserDaoProxy(new UserDaoImpl());
    43. UserDao userDao = (UserDao) Proxy.newProxyInstance(TestSpring.class.getClassLoader(), clazzs, userDaoProxy);
    44. userDao.add();
    45. }
    46. }

    术语

    • 连接点:可以增强的方法称为连接点。
    • 切入点:实际增强的方法称为切入点
    • 通知:实际增强的逻辑称为通知
    1. 前置通知
    2. 后置通知
    3. 环绕通知
    4. 异常通知
    5. 最终通知
    • 切面:是动作,把通知应用到切入点过程称为切面。

    AspectJ

    AspectJ不是Spring组成部分,是一个独立的框架,Spring框架一般基于AspectJ实现AOP操作。

    切入点语法结构

    execution([权限修饰符] [返回类型] [类全路径].[方法名称]([参数列表]))

    1. @Aspect
    2. @Component
    3. public class UserDaoAspect {
    4. /**
    5. * 相同切入点抽取
    6. */
    7. @Pointcut(value = "execution(* com.ww.spring5.dao.Impl.UserDaoImpl.add())")
    8. public void logPointCut() {
    9. }
    10. /**
    11. * 前置通知
    12. */
    13. @Before(value = "execution(* com.ww.spring5.dao.Impl.UserDaoImpl.add())")
    14. public void beforeAdd() {
    15. System.out.println("beforeAdd......");
    16. }
    17. /**
    18. * 后置通知
    19. */
    20. @After(value = "execution(* com.ww.spring5.dao.Impl.UserDaoImpl.add())")
    21. public void afterAdd() {
    22. System.out.println("afterAdd......");
    23. }
    24. /**
    25. * 环绕通知
    26. */
    27. @Around(value = "logPointCut()")
    28. public void aroundAdd(ProceedingJoinPoint joinPoint) throws Throwable {
    29. System.out.println("aroundAdd before......");
    30. joinPoint.proceed(); // 执行被增强的方法【UserDaoImpl.add()】
    31. System.out.println("aroundAdd after......");
    32. }
    33. /**
    34. * 最终通知
    35. */
    36. @AfterReturning(value = "execution(* com.ww.spring5.dao.Impl.UserDaoImpl.add())")
    37. public void afterReturningAdd() {
    38. System.out.println("afterReturningAdd......");
    39. }
    40. /**
    41. * 异常通知
    42. */
    43. @AfterThrowing(value = "execution(* com.ww.spring5.dao.Impl.UserDaoImpl.add())")
    44. public void afterThrowingAdd() {
    45. System.out.println("afterThrowingAdd......");
    46. }
    47. }
    48. public class TestSpring {
    49. @Test
    50. public void testAspectJ() {
    51. ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
    52. UserDao userDao = ac.getBean("userDaoImpl", UserDao.class);
    53. userDao.add();
    54. }
    55. }
  • 相关阅读:
    MockingBird,手把手教你克隆您的声音,AI代言人,惊艳你的耳朵!
    Python如何不加载图片获取图片的尺寸(宽和高)?
    力扣2578. 最小和分割
    CMU 10-414/714: Deep Learning Systems --hw1
    Python+Appium自动化搭建新手教程
    华为eNSP配置专题-NAT的配置
    ceph存储快速部署
    【Vue】构建vue项目的几种方法以及区别
    Oracle和Random Oracle
    浙大工商管理硕士(MBA)创客班适合哪些人群申请报考?
  • 原文地址:https://blog.csdn.net/ww_kobe/article/details/132644708