@Resource 和 @Autowired 注解都是用来实现依赖注入的,
@Resource 默认按 byName 自动注入,@Autowired 默认按 byType 自动注入,
@Resource 有两个重要的属性,分是 name 和 type,
@Resource(name="xxx"),使用 byName 策略自动注入,
Spring 将 name 属性解析为 bean 的名字(最需要重新理解的就是这个bean名字),即寻找 id="xxx" 的 bean,将这个 bean 注入到 @Resource 注解的方法中。
基于 Annotation 的 AOP_Proxy 过程理解如下:
测试类 TestSpring 调用方法执行
UserAction ua1 = factory.getBean("userAction", UserAction.class);
即从配置文件 beans.xml 中查找 id="userAction" 的 bean,由 Spring 创建对象并返回创建的对象,
备注:factory.getBean("userAction", UserAction.class); 第二个参数,意思是把拿到的对象强制转换为对应的类,
而 beans.xml 中没有 id="userAction" 的 bean,基于Annotation的自动扫描策略找到 @Controller("userAction") 的 UserAction 类,
在里面找到
@Resource
public void setUserService(IUserService userService) {
this.userService = userService;
}
即默认 byName 注入,
@Resource(name="userService")对应去找 <bean id="userService" >,同样在配置文件中未找到,于是找到对应的类
@Service("userService")//业务层一般使用@Service
public class UserService implements IUserService {
@Resource(name="messageDynamicDao")
public void setMessageDao(IMessageDao messageDao) {
this.messageDao = messageDao;
}
//默认通过名称注入,在JSR330中提供了@Inject来注入
@Resource(name="userDynamicDao")
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
}
其中 @Resource(name="userDynamicDao") 会去 beans.xml 中查找,对应找到
<bean id="userDynamicDao" class="org.zttc.itat.spring.proxy.LogProxy" factory-method="getInstance">
<constructor-arg ref="userDao"/>
</bean>
此 bean 的实现类是 class="org.zttc.itat.spring.proxy.LogProxy" ,这是一个代理类,
使用工厂方法 factory-method="getInstance" ,即调用 LogProxy 中的 getInstance 获取代理对象,
LogProxy 没有 getter 和 setter 方法,不能用 <property/> 注入属性,只能用构造函数 <constructor-arg ref="userDao"/> 注入,
ref="userDao" 即抽取 beans.xml 中的 <bean id="userDao"> 来注入到<bean id="userDynamicDao"> 中,
找到对应的userDao
@Repository("userDao")//@Repository一般用于DAO的注入
public class UserDao implements IUserDao {
add方法;
delete方法;
load方法;
}
将 userDao 对象作为被代理对象参数注入到 getInstance(Object o) 。
源代码:
TestSpring
package org.zttc.itat.spring.test;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.zttc.itat.spring.action.UserAction;
import org.zttc.itat.spring.model.HelloWorld;
import org.zttc.itat.spring.model.User;
public class TestSpring {
//创建Spring的工厂
private BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
@Test
public void testUser01() {
UserAction ua1 = factory.getBean("userAction", UserAction.class);
User u = new User(1,"悟空");
ua1.setUser(u);
ua1.add();
ua1.delete();
ua1.load();
//
// UserAction ua2 = factory.getBean("userAction", UserAction.class);
// ua2.add();
}
}
beans.xml
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 打开Spring的Annotation支持 -->
<context:annotation-config/>
<!-- 设定Spring 去哪些包中找Annotation -->
<context:component-scan base-package="org.zttc.itat.spring"/>
<bean id="userDynamicDao" class="org.zttc.itat.spring.proxy.LogProxy" factory-method="getInstance">
<constructor-arg ref="userDao"/>
</bean>
<bean id="messageDynamicDao" class="org.zttc.itat.spring.proxy.LogProxy" factory-method="getInstance">
<constructor-arg ref="messageDao"/>
</bean>
</beans>
UserAction
package org.zttc.itat.spring.action;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.zttc.itat.spring.model.User;
import org.zttc.itat.spring.service.IUserService;
//@Component("userAction")
@Controller("userAction")//MVC的控制层一般使用@Controller
@Scope("prototype")
public class UserAction {
private User user;
private IUserService userService;
private int id;
private List<String> names;
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
public IUserService getUserService() {
return userService;
}
@Resource
public void setUserService(IUserService userService) {
this.userService = userService;
}
public UserAction() {
}
public UserAction(IUserService userService) {
super();
this.userService = userService;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
// public IUserService getUserService() {
// return userService;
// }
//
// public void setUserService(IUserService userService) {
// this.userService = userService;
// }
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void add() {
userService.add(user);
}
public void delete() {
userService.delete(id);
}
public void load() {
userService.load(id);
}
}
UserService
package org.zttc.itat.spring.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.zttc.itat.spring.dao.IMessageDao;
import org.zttc.itat.spring.dao.IUserDao;
import org.zttc.itat.spring.model.User;
//@Component("userService")
@Service("userService")//业务层一般使用@Service
public class UserService implements IUserService {
private IUserDao userDao;
private IMessageDao messageDao;
public IUserDao getUserDao() {
return userDao;
}
public IMessageDao getMessageDao() {
return messageDao;
}
@Resource(name="messageDynamicDao")
public void setMessageDao(IMessageDao messageDao) {
this.messageDao = messageDao;
}
//默认通过名称注入,在JSR330中提供了@Inject来注入
@Resource(name="userDynamicDao")
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
@Override
public void add(User user) {
messageDao.add();
messageDao.delete();
userDao.add(user);
}
@Override
public void delete(int id) {
userDao.delete(id);
}
@Override
public User load(int id) {
return userDao.load(id);
}
}
LogProxy
package org.zttc.itat.spring.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.zttc.itat.spring.model.LogInfo;
/**
* 1、写一个类实现InvocationHandler接口
* @author Administrator
*
*/
public class LogProxy implements InvocationHandler {
private LogProxy(){}
//2、创建一个代理对象
private Object target;
//3、创建一个方法来生成对象,这个方法的参数是要代理的对象,getInstacne所返回的对象就是代理对象
public static Object getInstance(Object o) {
//3.1、创建LogProxy对象
LogProxy proxy = new LogProxy();
//3.2、设置这个代理对象
proxy.target = o;
//3.3、通过Proxy的方法创建代理对象,第一个参数是要代理对象的classLoader
//第二个参数是要代理对象实现的所有接口,第三个参数是实现类InvocationHandler的对象
//此时的result就是一个代理对象,代理的是o
Object result = Proxy.newProxyInstance(o.getClass().getClassLoader(),
o.getClass().getInterfaces(), proxy);
return result;
}
/**
* 当有了代理对象之后,不管这个代理对象执行什么方法,都会调用以下的invoke方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// if(method.getName().equals("add")||method.getName().equals("delete")) {
// Logger.info("进行了相应的操作");
// }
Object obj = method.invoke(target, args);
if(method.isAnnotationPresent(LogInfo.class)) {
LogInfo li = method.getAnnotation(LogInfo.class);
Logger.info(li.value());
}
return obj;
}
}
UserDao
package org.zttc.itat.spring.dao;
import org.springframework.stereotype.Repository;
import org.zttc.itat.spring.model.User;
//等于完成了<bean id="userDao" class="org.zttc.itat.spring.UserDao"/>
//@Component("userDao")//公共的创建bean的Annotation
@Repository("userDao")//@Repository一般用于DAO的注入
public class UserDao implements IUserDao {
@Override
public void add(User user) {
System.out.println("添加了"+user);
}
@Override
public void delete(int id) {
System.out.println("delete :"+id);
}
@Override
public User load(int id) {
System.out.println("load:"+id);
return null;
}
}