Java框架之Spring(三)
本文主要介绍Spring中,
1 Bean 的 init-method 和 destroy-method
2 集合类型的装配
3 注解方式装配
4 以自动扫描把组件纳入spring容器中管理
5 代理模式
一、Bean 的 init-method 和 destroy-method
以前在学Servlet的时候,有 init 和 destory 等时机,用Spring管理的bean 也可以有类似的时机,对于单实例的Bean ,在创建的时候会调用 initAAA() 方法,在销毁的时候,会调用 destroyAAA()。
<bean name="userAction_name" class="cat.action.UserAction" init-method="initAAA" destroy-method="destroyAAA" >
public class UserAction {
public void initAAA(){
System.out.println("initAAA调用了,这是在初始的时候调用的");
} public void destroyAAA(){
System.out.println("destroyAAA调用了,这是在销毁的时候调用的");
} }
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); //会调用 initAAA()
ctx.getBean("userAction_name");
ctx.close(); //销毁容器 会调用destroyAAA()
//对于多实例的bean
<bean name="userAction_name" class="cat.action.UserAction" init-method="initAAA" destroy-method="destroyAAA" scope ="prototype" >
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
ctx.getBean("userAction_name"); //调用 initAAA()
ctx.close(); //销毁容器 不会会调用destroyAAA() //因为对多实例的bean spring 在创建之后,就不再对它的生命周期负责
二、集合类型的配置
1)Set集合
public class UserAction {
private Set<String> mySet ; //由Spring把这个集合的内容注进来 public void execute(){
for(String s:mySet){
System.out.println(s);
}
} public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
} //配置文件
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="mySet">
<set>
<value>李白</value>
<value>唐太宗</value>
<value>小杜</value>
</set>
</property>
2)List 集合
//和Set完全相同 只不过是上面的中的 set 要完全改成 list
<set>
<value>李白</value>
<value>唐太宗</value>
<value>小杜</value>
</set>
3) Properties 集合
public class UserAction {
private Properties myProps; //不要忘了生成set方法
public void execute(){
Set<String> keySet= myProps.stringPropertyNames();
Iterator<String> it=keySet.iterator();
while(it.hasNext()){
String key=it.next();
System.out.println(key+":"+myProps.getProperty(key));
} } ...
}
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="myProps">
<props>
<prop key="key1">夏天</prop>
<prop key="key2">秋天</prop>
<prop key="key3">冬天</prop>
<prop key="key4">春天</prop>
</props>
</property>
</bean>
4) map集合
public class UserAction {
private Map<String,String> myMap; //要生成set 方法
public void execute(){
Set<Map.Entry<String, String>> entrySet = myMap.entrySet();
Iterator<Map.Entry<String, String>> it= entrySet.iterator();
while(it.hasNext()){
Map.Entry<String, String > item= it.next();
System.out.println(item.getKey()+":"+item.getValue());
}
}
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="myMap">
<map>
<entry key="m_1" value="AK-47"></entry>
<entry key="m_2" value="M_16"></entry>
<entry key="m_3" value="M_P5"></entry>
</map>
</property>
</bean>
三、注解方式装配
附 : p 这个名称空间的作用就是简化属性的编写
<bean name="userInfo" class="cat.beans.UserInfo" >
<property name="id" value="1"></property>
<property name="userName" value="赵强"></property>
<property name="password" value="admin"></property>
<property name="note" value="这是备注"></property>
</bean>
上面的等价于:
<bean name="userInfo" class="cat.beans.UserInfo"
p:id="1"
p:userName="赵强"
p:note="这是备注"
p:password="admin123"
>
</bean>
1) 引入jar包 common-annotations.jar
2) 引用入名称空间 context
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" //这是引入的名称空间
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
//上面这个是名称空间所对应的xsd文件的路径 <context:annotation-config /> //把Spring 对注解的处理器注册到Spring中
<bean name="userAction_name" class="cat.action.UserAction" />
<bean name="userDao_name" class="cat.dao.UserDaoImpl" />
</beans>
public class UserAction {
@Resource //用这个注解,进行注入
private IUserDao dao; public void execute(){
dao.addUser();
dao.updateUser();
}
}
说明:
1.@Resource 是 javax.annotation.Resource 包下的
2.@Resource 默认是按名称进行装配,再按类型进行装配(在不指定名称的情况下),如果指定了名称.它就严格的按名称进行装配
3.这个注解也可以写在set方法上
//下面的例子,使用了名称
public class UserAction {
@Resource(name="xxxxxx_dao")
private IUserDao dao; public void execute(){
dao.addUser();
dao.updateUser();
}
}
<bean name="userAction_name" class="cat.action.UserAction" />
<bean name="xxxxxx_dao" class="cat.dao.UserDaoImpl" /> //它会被注入
<bean name="oracleDao" class="cat.dao.UserDaoOracleImpl" />
4.@Autowired 注解和 @Resource 功能类似,它是在 org.springframework.beans.factory.annotation.Autowired 默认是按类型装配 ,默认情况下,它要求依赖对象必须存在 ,如果对象是null 值 ,可以设置它的 required=false ,如果也想按名称装配 ,要和另一个注解一起使用
//例子 使用 @Autowired
public class UserAction {
@Autowired(required=false) @Qualifier("oracleDao")
private IUserDao dao; //没有给它生成get 和 set 方法 public void execute(){
dao.addUser();
dao.updateUser();
}
}
四、以自动扫描把组件纳入spring容器中管理
开启自动扫描的方式
<context:component-scan base-package="cat.beans" />
<context:component-scan base-package="cat.dao" /> //如果用这种方式开启了自动扫描,就不用加
<context:annotation-config />
它会自动在包下查找类 并纳入Spring管理,包扩子包。它会自动找 带有 @Service @Controller @Repository @Component 的类
==@Service 用于业务层
==@Controller 用于控制层
==@Repository 用于数据访问层
==@Component 用于其他
目前只是一种规范,实际上用哪个都可以
说明:
1) 可以指定bean的名称
@Controller("userAction_name") //传参,指定名称
public class UserAction {
...
}
2) 默认情况下,这样配置的bean是单例的,如果是多例
@Controller("userAction_name") @Scope("prototype")
public class UserAction { }
//例子 控制层
@Controller("userAction_name") @Scope("prototype")
public class UserAction { @Resource(name="userDaoOracleImpl")
private IUserDao dao; public void execute(){
dao.addUser();
dao.delUser();
}
} //数据访问层
@Repository
public class UserDaoOracleImpl implements IUserDao {
public void addUser() {
System.out.println("addUser方法被调用了Oracle版的 ");
}
public void delUser() {
System.out.println("delUser方法被调用了Oracle版的 ");
} public void updateUser() {
System.out.println("updateUser方法被调用了Oracle版的 ");
}
} //测试
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserAction action =(UserAction) ctx.getBean("userAction_name");
action.execute(); //对于纳入自动扫描的bean ,它的名称默认是类名, 首字母小写
注意:使用了注解方式以后,原来的初始化和销毁方法应该怎么配置呢?
@Component @Scope("prototype")
public class UserAction { ...
@PostConstruct //初始方法
public void initAAA(){
System.out.println("初始化的方法被调用了");
} @PreDestroy //销毁方法
public void destoryAAA(){
System.out.println("销毁的方法被调用了");
}
五、代理模式
因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗?
你有想过限制访问某个对象,也就是说,提供一组方法给普通用户, 特别方法给管理员用户?以上两种需求都非常类似,并且都需要解决一个更大的问题:你如何提供一致的接口给某个对象让它可以改变其内部功能,或者是从来不存在的功能? 可以通过引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象的一个替身。即代理对象。它可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务。
业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点
静态代理
由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前,就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
//1) 接口
public interface IUserDao {
void addUser();
void delUser();
void updateUser();
void searchUser();
} //2) 实现类 //委托类
public class UserDaoImpl implements IUserDao{
public void addUser() {
System.out.println("addUser方法执行了");
} public void delUser() {
System.out.println("delUser方法执行了");
} public void updateUser() {
System.out.println("updateUser方法执行了");
} public void searchUser() {
System.out.println("searchUser方法执行了");
}
}
//3) 代理类
public class UserDaoProxy implements IUserDao {
private UserDaoImpl userDaoImpl=new UserDaoImpl(); //代理类中,要有一个被委托的类的实例对象
private String path="log.txt"; public void addUser() {
try {
userDaoImpl.addUser();
BufferedWriter bw=new BufferedWriter(new FileWriter(path));
bw.write(new Date()+": 执行了添加用户操作 ");
bw.newLine();
bw.close(); } catch (IOException e) {
e.printStackTrace();
}
} public void delUser() {
try {
userDaoImpl.delUser();
BufferedWriter bw=new BufferedWriter(new FileWriter(path));
bw.write(new Date()+": 执行了删除用户操作 ");
bw.newLine();
bw.close(); } catch (IOException e) {
e.printStackTrace();
}
} public void updateUser() {
try {
userDaoImpl.updateUser();
BufferedWriter bw=new BufferedWriter(new FileWriter(path));
bw.write(new Date()+": 执行了更新用户操作 ");
bw.newLine();
bw.close(); } catch (IOException e) {
e.printStackTrace();
}
} public void searchUser() {
long begin=System.currentTimeMillis();
userDaoImpl.searchUser();
long end=System.currentTimeMillis(); System.out.println("查询用户一共用了:" +(end-begin) +"ms");
} }
//3) 代理工厂
public class static UserDaoProxyFactory {
public IUserDao getUserDao(){
return new UserDaoProxy();
}
}
//4) 测试
public static void main(String[] args) {
IUserDao dao=UserDaoProxyFactory.getUserDao();
dao.addUser();
dao.updateUser();
dao.delUser();
dao.searchUser();
}
静态代理的缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
Java框架之Spring(三)的更多相关文章
- java框架之Spring(2)-注解配置IOC&AOP配置
注解配置IoC 准备 1.要使用注解方式配置 IoC,除了之前引入的基础 jar 包,还需要引入 spring-aop 支持包,如下: 2.在 applicationContext.xml 中引入 c ...
- java框架篇---spring AOP 实现原理
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- Java框架之Spring(四)
本文主要讲述在Spring中 1 注解方式装配 2 以自动扫描把组件纳入spring容器中管理 3 面象切面编程-代理的jdk 版实现 4 使用 Cglib 生成代理 5 aop编程的一些概念 6 使 ...
- Java - 框架之 Spring
一. IOC 和 DI IOC : 控制反转,将对象的创建权反转给了 Spring.DI : 依赖注入,前提是必须要有 IOC 的环境,Spring 管理这个类的时候将类的依赖的属性注入(设置)进来 ...
- java框架篇---spring hibernate整合
在会使用hibernate 和spring框架后 两个框架的整合就变的相当容易了, 为什么要整合Hibernate?1.使用Spring的IOC功能管理SessionFactory对象 LocalSe ...
- java框架篇---spring aop两种配置方式
第一种:注解配置AOP 注解配置AOP(使用 AspectJ 类库实现的),大致分为三步: 1. 使用注解@Aspect来定义一个切面,在切面中定义切入点(@Pointcut),通知类型(@Befor ...
- java框架篇---spring IOC 实现原理
IOC(DI):其实这个Spring架构核心的概念没有这么复杂,更不像有些书上描述的那样晦涩.java程序员都知道:java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用 ...
- Java框架之Spring MVC(二)
一.Spring MVC 验证 JSR 303 是ajvaEE6 中的一项子规范 ,叫 Bean Validation 用于对javaBean中的字段进行校验. 官方的参考实现是: Hibernate ...
- Java框架之Spring MVC(一)
一.Spring简介 Spring MVC是当前最优秀的 MVC 框架,自从Spring 2.5 版本发布后,由于支持注解配置,易用性有了大幅度的提高.Spring 3.0 更加完善,实现了对 Str ...
随机推荐
- UNIGUI与UNIURLFRAME的互动
UniSession.JSCode('name_'+MainForm.UniURLFrame1.name+'_'+MainForm.UniURLFrame1.JSName+'.myinput4.inn ...
- Android开发 - 掌握ConstraintLayout(二)介绍
介绍 发布时间 ConstraintLayout是在2016的Google I/O大会上发布的,经过这么长时间的更新,现在已经非常稳定. 支持Android 2.3(API 9)+ 目前的Androi ...
- 使用FFmpeg如何转发一个RTSP视频流
版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/6930221.html 转发RTSP流,这类需求一般出现于转发一些摄像头采集视频,并在摄像头上做RTSP ...
- Javascript多线程
最近项目中要用一个倒计时,但是当弹窗的时候倒计时会被阻塞,所以我想到使用Javascript多线程解决该问题. 虽然JavaScript是单线程的,但是通过worker可以让Javascript另外开 ...
- JavaScript实现HTML页面集成QQ空间分享功能
<!DOCTYPE HTML> <html> <head> <title>QQ空间分享</title> <meta http-equi ...
- RabbitMQ服务端配置详解
RabbitMQ支持三种配置方式: 1) 读取环境变量中配置, 这包括shell中环境变量和rabbitmq-env.conf/rabbitmq-env-conf.bat文件中配置的环境变量 可配置如 ...
- Python函数学习——作用域与嵌套函数
全局与局部变量 在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量. 全局变量作用域是整个程序,局部变量作用域是定义该变量的函数. 当全局变量与局部变量同名时,在定义局部变量的函数内 ...
- cannot download, /home/azhukov/go is a GOROOT, not a GOPATH
问题详情: go环境安装好后,运行go代码也没有问题 下载govendor包的时候提示: cannot download, /home/azhukov/go is a GOROOT, not a GO ...
- msysGit在GitHub代码托管
(转:http://www.cnblogs.com/xing901022/p/4388190.html) 代码的管理,在日常开发中是很重要的环节,程序员的修炼三部曲——版本控制,单元测试,项目自动化. ...
- IMEI
IMEI(International Mobile Equipment Identity)是国际移动设备身份码的缩写,国际移动装备辨识码,是由15位数字组成的"电子串号",它与每台 ...