问题导读:

1.Spring AOP 简单实例

2.Spring bean 生命周期


解决方案:

 

AOP

1.概念


  • 面向切面的编程
  • 软件要运行,除了自身核心功能之外往往需要其他很多服务来支持,比如:日志、事务管理、和安全等系统服务,这些服务被成为横切关注点,他们要跨越系统的多个组件
  • 正常将这些代码写到组件中会出现,代码重复,混乱等问题,无论怎么处理总会让核心代码怪怪的,aop就是这个时候出现的
  • aop总能确保pojo的简单性

2.实现


2.1 jar



Java EE - AOP 和 spring 的bean 生命周期_初始化



2.2 beans


2.2.1 Speaker


package com.lpl.spring;

public interface Speaker {
public void sayHello();
public void sayGoodbye();
}



package com.lpl.spring;

import org.springframework.stereotype.Component;

@Component
public class EnglishSpeaker implements Speaker{

@Override
public void sayHello() {
System.out.println("hello!");
}

@Override
public void sayGoodbye() {
// TODO Auto-generated method stub
System.out.println("goodbye!");
}
}


2.2.3 ChineseSpeaker


package com.lpl.spring;

import org.springframework.stereotype.Component;

@Component
public class ChineseSpeaker implements Speaker{
@Override
public void sayHello() {
System.out.println("你好");
}

@Override
public void sayGoodbye() {
// TODO Auto-generated method stub
System.out.println("再见");
}


}


2.3 Advice(通知)- SpeakAdvice


package com.lpl.spring;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class SpeakAdvice implements MethodInterceptor {

@Override
//横切功能的代码
public Object invoke(MethodInvocation method) throws Throwable {
// 业务方法执行完需要实现的横切面的代码
System.out.println("---Start---");
// 调用业务方法
Object val = method.proceed();
// 业务方法完成后需要实现的横切面的代码
System.out.println("---End---");

return val;
}

}



2.4 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-autowire="byType">
<!-- 配置基于注解的开发-->
<context:annotation-config/>
<context:component-scan base-package="com.lpl.spring"></context:component-scan>

<!-- AOP -->
<!-- 通知 advice-->
<bean id="speakAdvice" class="com.lpl.spring.SpeakAdvice"></bean>

<!-- 切面 advisor-->
<bean id="speakAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="speakAdvice"></property>
<!-- 切入点 -->
<property name="pattern" value=".*say.*"></property>
</bean>

<!--使用DefaultAdvisorAutoProxyCreator,它会自动搜寻容器内的所有Advisor,然后根据各个
Advisor所提供的拦截信息,为符合条件的容器中的目标对象生成相应的代理对象。
使用DefaultAdvisorAutoProxyCreator对容器内所有bean定义对应的对象进行自动代理之后,
我们从容器中取得的对象实例,就都是代理后已经包含了织入的横切逻辑的代理对象了。-->

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

</beans>




2.5 测试


package com.lpl.spring;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
Speaker englishSpeaker = (Speaker) factory.getBean("englishSpeaker");
englishSpeaker.sayHello();
englishSpeaker.sayGoodbye();
Speaker chineseSpeaker = (Speaker) factory.getBean("chineseSpeaker");
chineseSpeaker.sayHello();
chineseSpeaker.sayGoodbye();
}
}


Java EE - AOP 和 spring 的bean 生命周期_spring_02






Spring Bean 生命周期





Java EE - AOP 和 spring 的bean 生命周期_spring_03




  • Spring对Bean进行实例化(相当于程序中的new Xx())
  • Spring将值和Bean的引用注入进Bean对应的属性中
  • 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
  • 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
  • 如果Bean实现了ApplicationContextAwaer接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把y应用上下文作为参数传入.(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )
  • 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)
  • 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。
  • 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法(作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )
  • 经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁
  • 如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。