Java EE - AOP 和 spring 的bean 生命周期
原创
©著作权归作者所有:来自51CTO博客作者peerslee的原创作品,请联系作者获取转载授权,否则将追究法律责任
问题导读:
1.Spring AOP 简单实例
2.Spring bean 生命周期
解决方案:
AOP
1.概念
- 面向切面的编程
- 软件要运行,除了自身核心功能之外往往需要其他很多服务来支持,比如:日志、事务管理、和安全等系统服务,这些服务被成为横切关注点,他们要跨越系统的多个组件
- 正常将这些代码写到组件中会出现,代码重复,混乱等问题,无论怎么处理总会让核心代码怪怪的,aop就是这个时候出现的
- aop总能确保pojo的简单性
2.实现
2.1 jar
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();
}
}
Spring Bean 生命周期
- 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实例销毁前执行的方法。