美文网首页
Spring IOC & Containers & AOP

Spring IOC & Containers & AOP

作者: Anan_楠 | 来源:发表于2021-03-18 22:56 被阅读0次

IOC

即Inversion of Control,控制反转,也叫依赖注入。

不使用Spring时,创建Service实例的主动权在Controller,即自己主动去new一个出来马上就可以使用。
使用Spring后,Controller不能主动去new Service类的实例,只有Spring才能够new Service类的实例,Action只能等Spring创建好实例后,将实例分配给它之后,才能够使用。

减少Bean的耦合度,实现Bean的可插拔

如下图代码,Dao层有两个UserDao的实现类,当需要从一个切换到另一个时,仅需把旧的实现类的@Repository注解注释掉,把新的实现类加上@Repository注解即可,Service层与Controller层的代码无需改动。

另:一般仅对可复用的逻辑类,即单例的类,加入注解,进行IOC管理,如Dao实现类,Service实现类,Controller类。

/* Dao层 */
//@Repository
public class UserDaoJdbcImpl implements UserDao {...}

@Repository
public class UserDaoHibernateImpl implements UserDao {...}

/* Service层 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Override
    public User getUser(int id) {
        return userDao.findById(id);
    }
}

/* Controller层 */
@Controller
@RequestMapping(path = "/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping(path = "/detail/{id}", method = RequestMethod.GET)
    @ResponseBody
    public User getUser(@PathVariable("id") int id) {
        return userService.getUser(id);
    }
}

控制Bean生命周期及作用域

Bean: 有Spring容器管理的Java 对象

使用@PostConstruct注解相关方法,可在Bean初始化时调用该方法。
使用@PreDestroy注解相关方法,可现在Bean销毁前调用该方法。

使用@Scope注解可控制Bean的作用域,默认为单例模式,若需要多个实例,可使用prototype(尽管一般很少使用)。

@Service
//@Scope("prototype")
public class UserServiceImpl implements UserService {
    
    @PostConstruct
    public void init() {
        System.out.println("init UserServiceImpl");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("destroy UserServiceImpl");
    }
}

Containers

BeanFactory & ApplicationContext

The Spring Framework comes with two IOC containersBeanFactory and ApplicationContext. The BeanFactory is the most basic version of IOC containers, and the ApplicationContext extends the features of BeanFactory.

BeanFactory loads beans on-demand. The beans defined in our BeanFactory will be loaded only when we explicitly call the getBean() method. While ApplicationContext loads all beans at startup.

Thus, BeanFactory is lightweight as compared to ApplicationContext. It's generally recommended to use the ApplicationContext, and we should use BeanFactory only when memory consumption is critical.

Resource res = new ClassPathResource("ioc-container-difference-example.xml");
BeanFactory factory = new XmlBeanFactory(res);
// 此时BeanFactory加载Bean
Student student = (Student) factory.getBean("student");

// 此时ApplicationContext加载Bean
ApplicationContext context = 
    new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");

ApplicationContext核心功能:获取Bean

// 1 实现ApplicationContextAware接口
class ExampleApplicationTests implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 2 重写setApplicationContext方法,获取ApplicationContext容器
        this.applicationContext = applicationContext;
    }

    // 3 使用ApplicationContext获取Bean
    public void testApplicationContext() {
        //  通过类型获取
        UserDao dao1 = applicationContext.getBean(UserDao.class);
        // 通过名字获取
        UserDao dao2 = (UserDao) applicationContext.getBean("userDaoHibernateImpl");
        // 通过类型和名字获取(当一个抽象类有多个实现类时)
        UserDao dao3 = applicationContext.getBean("userDaoHibernateImpl", UserDao.class);
    }
}

AOP

即Aspect Oriented Programming, 面向切面编程

AOP.png

JoinPoint:连接点,即目标类中所有可能被切入的方法。
PointCut:切入点,即目标类中实际被切入的方法。
如:一个类中有方法1,方法2, 方法3,则这三个方法都是连接点,如果选择方法1进行切入,则方法1就为切入点。

Advice:通知,即用于规定何时对切入点进行何种操作。
Aspect:切面,包含了PointCut和Advice的类。

织入:将Advice中的操作应用与切点的过程。

如果目标类实现了接口,采用JDK的动态代理实现AOP,原理是Method方法反射
如果目标类没有实现接口,采用用CGLIB实现AOP,原理是对代理的目标类生成一个子类,并覆盖其中方法实现增强。(由于是继承目标类的方式,故无法对static、private、final修饰的方法进行代理)

JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。

@Component
@Aspect
public class LogAspect {
    // 说明切入点为返回值任意的 com.nowcoder.example.service包下的所有类的所有方法
    @Pointcut("execution(* com.nowcoder.example.service.*.*(..))")
    private void serviceAccess() { }
    
    @Before("serviceAccess()")
    public void before() {
        System.out.println("log before");
    }

    @AfterThrowing("serviceAccess()")
    public void afterThrowing() {
        System.out.println("log afterThrowing");
    }

    @AfterReturning("serviceAccess()")
    public void afterReturning() {
        System.out.println("log afterReturning");
    }

    @After("serviceAccess()")
    public void after() {
        System.out.println("log after");
    }

  // Around方式功能强,但代码出错时,影响范围也大,一般不使用
    @Around("serviceAccess()")
    public Object log(ProceedingJoinPoint joinPoint) {
        Object obj = null;
        try {
            System.out.println("log before");
            // 调用切入点的方法
            obj = joinPoint.proceed();
            System.out.println("log afterReturning");
        } catch (Throwable throwable) {
            System.out.println("log afterThrowing");
        } finally {
            System.out.println("log after");
        }
        return obj;
    }
}

相关文章

  • Spring IOC & Containers & AOP

    IOC 即Inversion of Control,控制反转,也叫依赖注入。 不使用Spring时,创建Servi...

  • Spring中的两大核心(Spring是一个IOC和AOP容器框架) IOC与aop IOC(spring的核心思...

  • 7

    Spring: 1、IOC,AOP IOC:Inversion of Control,控制反转 AOP:Aspec...

  • Spring AOP 要点

    Spring对AOP的支持 Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC...

  • Spring AOP实战和源码解析

    Spring AOP简介 说起Spring框架,我们最先想到的就是IOC和AOP了,如果说IOC是Spring的核...

  • Spring 基础5 —— AOP 与事务

    Spring 的 AOP 支持 Spring 的 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其...

  • AOP

    java创建对象的方法(5种): Spring AOP: spring分为: 1、IOC/DI 2、AOP AOP...

  • Spring要点

    1.spring IOC AOP原理: IoC(Inversion of Control): IoC就是应用本身...

  • 2019-05-23 Spring IOC 学习

    一、Spring Ioc/AOP 底层原理 1 IoC 引用 Spring 官方原文:This chapter c...

  • IOC和AOP

    IoC与AOP的那点事儿[%5Bhttp://blog.didispace.com/spring-ioc-aop/...

网友评论

      本文标题:Spring IOC & Containers & AOP

      本文链接:https://www.haomeiwen.com/subject/twrmcltx.html