1.Spring容器实例化
例子1:
String conf = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
CostAction action = (CostAction)ac.getBean("costAction");
System.out.println(action.getClass().getName());
action.addCost();
例子2:
String[] confs = {"applicationContext.xml"};
ApplicationContext ac = new ClassPathXmlApplicationContext(confs);
BeanUtil util = (BeanUtil)ac.getBean("beanUtil");
util.showMessage();
2.容器对Bean组件管理
<!-- 定义一个Bean组件,id|name用于指定组件标示符,class用于指定组件实现类 -->
<bean id="costDao"
scope="singleton"
lazy-init="true"
init-method="myinit"
class="org.tarena.dao.impl.JdbcCostDAO" >
</bean>
注:
id|name:用于指定组件标示符
class:用于指定组件实现类
scope:singleton单例,prototype非单例
lazy-init:单例延迟创建
init-method:设置初始化参数的方法
destroy-method:销毁之前调用的方法
3.IOC机制
原理DI技术实现:依赖注入。为Bean对象里的属性注入值
3.1.DI注入技术有以下几种实现
1).setter方式注入,name与setter方法一致
<property name="Bean对象里的属性" ref="Bean对象的ID"></property>
2).构造方法注入 index参数索引
<constructor-arg index="0" ref="Bean对象的ID"></constructor-arg>
3.2.注入各种不同的类型的数据
1)注入一个Bean对象
<property name="被注入的属性名字" ref="Bean的ID名称"> </property>
2)注入一个基本类型对象
<property name="被注入的属性名字" value="基本类型值"> </property>
3)注入list
例子1:
<property name="被注入的属性名字">
<list>
<value>值1</value>
<value>值2</value>
<value>值3</value>
</list>
</property>
例子2:
<property name="被注入的属性名字">
<list>
<ref>值</ref>
<ref>值</ref>
<ref>值</ref>
</list>
</property>
4)注入set集合
<property name="被注入的属性名字">
<set>
<value>值</value>
<value>值</value>
<value>值</value>
</set>
</property>
5)注入map集合
<property name="被注入的属性名字">
<map>
<entry key="" value=""></entry>
<entry key="" value=""></entry>
<entry key="" value=""></entry>
</map>
</property>
6)注入Properties
<property name="被注入的属性名字">
<props>
<prop key="">值</prop>
<prop key="">值</prop>
</props>
</property>
4.AOP机制
AOP机制的实现原理:动态代理机制
4.1.AOP使用步骤
a.引入Spring的IOC和AOP开发包
b.添加Spring容器配置文件
c.将共通处理封装成一个独立Bean组件
d.采用AOP配置将Bean组件作用到其它目标组件及其方法上
AOP配置 例子:
<!-- 利用AOP机制 -->
<bean id="loggerBean"
class="org.tarena.aspect.LoggerBean">
</bean>
<aop:config>
<!-- 切入点,指定目标组件 -->
<aop:pointcut id="actionPointcut"
expression="within(org.tarena.action..*)"/>
<!-- 方面,将loggerBean定义为方面组件 -->
<aop:aspect id="loggerAspect" ref="loggerBean">
<!-- 通知,指定loggerBean功能在action方法前调用 -->
<aop:around pointcut-ref="actionPointcut"
method="logger"/>
</aop:aspect>
</aop:config>
4.2.AOP相关概念
方面(Aspect):封装共通处理的组件
切入点(Pointcut):目标对象及方法
连接点(JoinPoint):方面和某一个目标方法的关联点
通知(Advice):指定方面功能在目标对象方法上执行的时机
目标组件(Target):使用方面功能的Bean组件
4.3.切入点表达式
利用表达式指定目标组件及方法
a.方法限定表达式
execution(修饰符? 返回类型 方法名(参数列表) throws异常?)
示例1:匹配容器中所有组件以add开始的方法
execution(* add*(..))
示例2:匹配CostService组件的所有方法
execution(* org.tarena.service.CostService.*(..))
示例3:匹配service包下所有类的所有方法
execution(* org.tarena.service.*.*(..))
示例4:匹配service包下及其子包中所有类的所有方法
execution(* org.tarena.service..*.*(..)
b.类型限定表达式
within(类型)
示例1:匹配CostService类中所有方法
within(org.tarena.service.CostService)
示例2:匹配service包下所有类的所有方法
within(org.tarena.service.*)
示例3:匹配service包及其子包所有类所有方法
within(org.tarena.service..*)
注:以上表达式可以用&&,||连接在一起,也可用!,(&):在xml中代表(&&)
4.4.通知类型
try{
// 前置通知--执行方面组件 <aop:before>
// 执行目标方法
// 后置通知--执行方面组件 <aop:after-returnning>
//以上加起来等于环绕通知
// ||
//环绕通知=前置通知+后置通知 <aop:around>
}catch(Exception ex){
// 异常通知--执行方面组件 <aop:after-throwing>
}finally{
// 最终通知--执行方面组件 <aop:after>
}
5.环绕通知:记录操作日志
5.1.配置
<!-- 利用AOP机制 -->
<bean id="loggerBean"
class="org.tarena.aspect.LoggerBean">
</bean>
<aop:config>
<!-- 切入点,指定目标组件 -->
<aop:pointcut id="actionPointcut"
expression="within(org.tarena.action..*)"/>
<!-- 方面,将loggerBean定义为方面组件 -->
<aop:aspect id="loggerAspect" ref="loggerBean">
<!-- 通知,指定loggerBean功能在action方法前调用 -->
<aop:around pointcut-ref="actionPointcut"
method="logger"/>
</aop:aspect>
</aop:config>
5.2.组件中的代码
环绕通知,自动给方面组件的方法传入参数:连接点 ProceedingJoinPoint pjp
通过连接点可以获得:
要执行的目标组件名称:String pjp.getTarget().getClass().getName();
要执行的目标方法名称:String pjp.getSignature().getName();
执行目标方法的方法:Object retVal = pjp.proceed();
// 在这之前是前置处理,之后是后续操作,类似于struts的拦截起
方面组件方法返回:return retVal
例子:
// 环绕通知处理方法,采用<aop:around>配置
public Object logger(ProceedingJoinPoint pjp) throws Throwable{
// 获取要执行的目标组件名称
String clazzName =
pjp.getTarget().getClass().getName();
// 获取要执行的目标方法名称
String methodName =
pjp.getSignature().getName();
// 利用类名.方法名去opt.properties中获取操作名
String key = clazzName+"."+methodName;
String name = PropertiesUtil.getValue(key);
System.out.println("XXX执行了"+name+"操作"+new Date());
Object retVal = pjp.proceed();// 执行目标方法
// TODO 后续处理
return retVal;
}
6.异常通知:记录异常日志
6.1.配置
<!-- 利用AOP机制 -->
<bean id="exceptionBean"
class="org.tarena.aspect.ExceptionBean">
</bean>
<aop:config>
<!-- 切入点,指定目标组件 -->
<aop:pointcut id="actionPointcut"
expression="within(org.tarena.action..*)"/>
<!-- 定义记录异常的方面组件 -->
<aop:aspect id="exceptionAspect" ref="exceptionBean">
<!-- 采用异常通知作用到action上 -->
<aop:after-throwing pointcut-ref="actionPointcut"
method="logger" throwing="ex"/>
</aop:aspect>
</aop:config>
6.2.方面组件中代码
Logger logger = Logger.getLogger(ExceptionBean.class);
// 记录目标方法抛出的异常信息
public void logger(Exception ex){
logger.error("发生异常"+ex);
StackTraceElement[] els = ex.getStackTrace();
logger.error(els[0]);
}
7.解析Properties
解决中文编码问题:
java中的native2ascii
public class PropertiesUtil {
private static Properties pros = new Properties();
static {
InputStream in = PropertiesUtil.class
.getClassLoader().getResourceAsStream(
"opt.properties");
try{
pros.load(in);
}catch(Exception ex){
ex.printStackTrace();
}
}
public static String getValue(String key){
String val = pros.getProperty(key);
if(val == null){
return "";
}
return val;
}
}
8.log4j
日志器组件(Logger)
输出器组件(Appender)
布局器组件(Layout)
ConsoleAppender:控制台输出
FileAppender:输出到文件
8.1.log4j.properties配置文件
#log4j.properties
#log4j.rootLogger=level,appender1,appender2..
log4j.rootLogger=error,myconsole
#appender
log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
#log4j.appender.myconsole=org.apache.log4j.FileAppender
#log4j.appender.myconsole.File=D:\\log.txt
#layout
log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout
8.2.级别有低到高
Logger logger = Logger.getLogger(TestLog4j.class);
logger.debug("调试信息");
logger.info("普通信息");
logger.warn("警告信息");
logger.error("异常信息");
logger.fatal("致命信息");
9.解析xml
public class PrivilegeReader {
private static List<Privilege> modules = new ArrayList<Privilege>();
static {
InputStream xml = PrivilegeReader.class.getClassLoader()
.getResourceAsStream("privileges.xml");
modules = toModuleList(xml);
}
// 通过id获取name
public static String getModuleNameById(String id){
List<Privilege> modules = getModules();
for(Privilege module : modules){
if(module.getId().equals(id)){
return module.getName();
}
}
return "";
}
private static List<Privilege> toModuleList(InputStream xml) {
List<Privilege> modules = new ArrayList<Privilege>();
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(xml);
Element root = doc.getRootElement();
List<Element> moduleElements = root.elements("privilege");
for (Element moduleElement : moduleElements) {
//Privilege是一个实体类有id,name,urls属性
Privilege module = new Privilege();
module.setId(moduleElement.attributeValue("id"));
module.setName(moduleElement.elementText("name"));
Element urlElement = moduleElement.element("urls");
List<Element> urlElements = urlElement.elements();
List<String> urls = new ArrayList<String>();
for (Element element : urlElements) {
urls.add(element.getText());
}
module.setUrls(urls);
modules.add(module);
}
return modules;
} catch (DocumentException e) {
e.printStackTrace();
throw new RuntimeException("", e);
}
}
public static List<Privilege> getModules() {
return modules;
}
public static void main(String[] args) {
List<Privilege> list = PrivilegeReader.getModules();
for (Privilege p : list) {
System.out.println(p.getId() + " " + p.getName()+""+p.getUrls());
}
}
}