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 ...
随机推荐
- 【转】Closeable, Readable, Flushable, Appendable
Closeable: package java.io; import java.io.IOException; public interface Closeable { /** * Closes th ...
- Maths | 为什么点积等价于投影后的乘积
目录 1. 复习点积 2. 点积的对称性 3. 矩阵与变换的关系 4. 一维矩阵也是一种线性变换 5. 最终解释:为什么是投影 先上结论: \(\boldsymbol v\)和\(\boldsymbo ...
- Oracle实现like多个值的查询
问题背景描述: 某天客户有一个需求,给定一批的手机号码或者电话号码,查询出相关的通话记录,以及相关的一些信息. 客户给定的被叫号码如图所示: 查询出来的结果如下图所示(本批次的结果不是上图导入的结 ...
- @WebFilter怎么控制多个filter的执行顺序
转自:http://blog.csdn.net/liming_0820/article/details/53332070 之前我们控制多个filter的执行顺序是通过web.xml中控制filter的 ...
- Thinking in Java Chapter 14
From Thinking in Java 4th Edition RTTI(Run-Time Type Information),运行时类型信息,使得你可以在程序运行时发现和使用类型信息.对RTTI ...
- while循环 格式化输出 密码本 编码的初识
第二天课程整理 while 循环 why : while ' 循环' 的意思 what : while 无限循环 how : 1.基本结构 while + 条件 循环的代码 初识循环 while tr ...
- LeetCode:144_Binary Tree Preorder Traversal | 二叉树的前序遍历 | Medium
题目:Binary Tree Preorder Traversal 二叉树的前序遍历,同样使用栈来解,代码如下: struct TreeNode { int val; TreeNode* left; ...
- jsp-静态包含和动态包含的区别
include指令是静态包含.静态包含的意思就是:把文件的代码内容都包含进来,再编译! include指令是静态包含,include行为是动态包含.其实include行为就是封装了request.ge ...
- 【sping揭秘】21、Spring动态数据源的切换
对于多个数据源的时候,我们如何切换不同的数据源进行数据库的操作呢? 当然我们可以直接定义2个DataSource,然后在每次获取connection的时候,从不同的DataSource中获取conne ...
- vertical-align_CSS参考手册_web前端开发参考手册系列
该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐.允许指定负长度值和百分比值.这会使元素降低而不是升高.在表单元格中,这个属性会设置单元格框中的单元格内容的对齐方式. <!DOCTYP ...