鉴于之前的博文中都是通过在xml中对bean进行配置的方式注入的,又加上博友的要求,决定对注解方式进行一个简单的讲解,这里不会涉及太复杂的程序,因为本文的目的是让看到这篇博文的广大博友能懂,而不是云里雾里的怎么也看不明白。
1. @Controller:标注一个控制器组件的类。
2. @Service:标注一个业务逻辑组件的类。
3. @Repository:标注一个Dao组件的类。
4. @Component:标注一个普通的类。
这几个注解主要用于标注Spring要进行实例化的类,一旦在某个类的上面标注了这样的注解,如果是单例模式的话,那么Spring在初始化的时候,就会将这些类实例化,而对于非单例模式的类,不取决于Spring容器本身,往往是客户端进行请求的时候,进行创建实例(Spring创建的),这些在之前的博文中已经进行过说明,请参考Spring进阶之路(7)-Bean的生命周期以及创建、销毁执行流程。
5. @Resource:按照名称(name)进行注入。该注解属于jdk中的注解,但是在项目中使用比较广泛。
6. @Autowired:按照类型匹配自动注入。
这里的两个注解主要用于为类中属性注入值。两个注解可以将(上面四个注解标注的类在Spring中实例化后的对象)注入到某些类的属性中。
7. @Scope("prototype"):默认的情况下是产生单例对象,在Scope的里面传了prototype的参数后,表明该类不是单例的,而是"多例的",不知道这么解释标准不标准,读者可以纠正。
8. @PostConstruct:指定bean的初始化方法与之前博文中配置文件指定的initMethod作用相同(Spring进阶之路(7)-Bean的生命周期以及创建、销毁执行流程),Spring会在Bean的依赖注入完成后回调这个方法。
9. @PreDestroy:指定bean的销毁之前的方法与Spring进阶之路(7)-Bean的生命周期以及创建、销毁执行流程这篇博文中配置文件指定的destroyMethod的作用是一样的,他会在bean销毁之前调用。
另外:
10: @Lazy:用于指定该类是否取消预初始化。指定参数boolean型true即可,下面不在赘述,这个注解比较简单。
11: @DependsOn:可以修饰类或者方法,用于强制初始化一些bean,例如:@DependsOn({"wy", "wangyang"}),这样在初始化之前会强制初始化里面的bean.
用注解进行自动注入bean的前提是在配置文件中配置了自动注入的支持。
控制器组件:
用到了@Controller、@Scope、@Resource、@Autowired四个注解,如果这里没有被注入进来的话,会在调用的地方抛出空指针异常,如果不抛出空指针就说明bean已经被注入进来了。
package com.siti.spring20160316;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
@Controller
@Scope("prototype")
public class UserAction {
@Resource
private UserService userService;
@Autowired
private Utils utils;
public boolean login(String userName, String password){
System.out.println("UserAction--login");
if(utils.check(userName)){
if(userService.login(userName, password)){
return true;
}
}
return false;
}
}
在这里说明下,一般我们开发中比较喜欢用接口,这里是为了看起来清楚没有采用接口的形式,避免读者看的云里雾里搞不清楚流程。
这里主要用到的注解有@Service(标注业务逻辑层)、@PostCustruct(标注的方法相当于initMethod)、@PreDestroy(标注的方法相当于destroyMethod)
package com.siti.spring20160316;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
/**
*
* @ProjectName SpringBlob
* @ClassName UserService
* @Description 一般情况下,都是采用接口的,这里没有使用接口,便于读者直接看清楚调用关系
* @author wy
* @date 2016-3-16
*
*/
@Service
public class UserService {
@Resource
private UserDao userDao;
public boolean login(String userName, String password){
System.out.println("UserService--login");
if(userDao.isExist(userName, password)){
return true;
}
return false;
}
@PostConstruct
public void init(){
System.out.println("UserService--init");
}
@PreDestroy
public void destroyMethod(){
System.out.println("UserService--destroyMethod");
}
}
DAO层
主要用到的注解有@Repository
由于这里属于模拟没有加入连接数据库部分的持久化操作,请见谅。
package com.siti.spring20160316;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public boolean isExist(String userName, String password){
System.out.println("UserDao--isExist");
if("wy".equals(userName)){
return true;
}
return false;
}
}
第一个输出比较两个得到的对象是不是同一个对象。读者可以自己检验其他的几个对象是不是同一个。因为UserAction类标注了@Scope的注解并指定其类型为prototype,那么这里应该是不一样的,输出false
package com.siti.spring20160316;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext20160316.xml");
UserAction action = (UserAction) context.getBean("userAction");
UserAction action2 = (UserAction) context.getBean("userAction");
System.out.println("这两个对象是否是同一个对象:" + action.equals(action2));
boolean bool = action.login("wy", "******");
if(bool){
System.out.println("登录成功!");
}else{
System.out.println("登录不成功!");
}
context.registerShutdownHook();
}
}
这里只是自己写了个注解,但是没有解析类是没办法去用的,读者可以试试看能不能自己写出他的处理类,可以共同交流下。
package com.siti.spring20160316;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)// 运行期间注入
@Target({ElementType.FIELD, ElementType.METHOD})// 可以标注在哪里,这里是属性和方法上
public @interface MyAutowired {
// 参数
public String name() default "";
}