今天来说一下Spring注解
注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好。不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就不会显得那么被动了。
1.@Configuration注解
1.1@Configuration + <context>
该类等价 与XML中配置beans,相当于Ioc容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean,与xml中配置的bean意思一样。
@Configuration注解的类必需使用<context:component-scanbase-package=”XXX”/>扫描.如下:
例:
程序结构图:
(1)首先建立Perons.java,person实体类
package com.zk.Bean; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Configuration public class Person { public Person() { System.out.println("Person初始化"); } }
(2)其次在建立MainApp.java
package com.zk.Main; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.zk.Bean.Person; public class MainApp { public static void main(String[]args) { ApplicationContext context = new AnnotationConfigApplicationContext(Person.class); } }
(3)ApplicationContext.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: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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <context:component-scan base-package="com.zk.Bean" /> </beans>
运行结果:
1.2、@Configuration启动容器+@Bean注册Bean,@Bean下管理bean的生命周期
(1)首先建立TestBean.java,实体类
package com.zk.Bean; import org.springframework.beans.factory.annotation.Value; public class TestBean { @Value("zk") private String name; private String url; private String password; @Override public String toString() { return "TestBean [name=" + name + ", url=" + url + ", password=" + password + "]"; } public void sayHello(){ System.out.println(name+":sayHello"); } public void start(){ System.out.println(name+":start"); } public void cleanup(){ System.out.println(name+":cleanup"); } }
(2)创建TestConfigure.java
package com.zk.Bean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration public class TestConfigure { public TestConfigure(){ System.out.println("TestConfiguration..."); } @Bean @Scope("prototype") TestBean testBean(){ return new TestBean(); } }
(3)创建ApplicationContext.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: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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <context:component-scan base-package="com.zk.Bean" /> </beans>
(4)创建TestMain.java
package com.zk.Bean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestMain { public static void main(String[]args) { // @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext ApplicationContext context=new AnnotationConfigApplicationContext(TestConfigure.class); //获取bean TestBean tb=(TestBean) context.getBean("testBean"); tb.sayHello(); } }
运行结果如下:
2.@Value注解
在程序中使用@Value的注解是为了给变量赋值,如上面的注解:
@Value("zk") private String name;
使用
// @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext ApplicationContext context=new AnnotationConfigApplicationContext(TestConfigure.class); //获取bean TestBean tb=(TestBean) context.getBean("testBean"); tb.sayHello();
调用getBean()方法可以获取到name的值。
3. @Controller, @Service, @Repository,@Component
目前4种注解意思是一样,并没有什么区别,区别只是名字不同。使用方法:
(1)创建com.zk.component,创建TestObject.java
package com.zk.component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.stereotype.Component; @Component public class TestObject { @PostConstruct public void contructbefore(){ System.out.println("初始化之前的操作"); } @PreDestroy public void contructAfter(){ System.out.println("初始化之后的操作"); } }
(2)创建com.zk.controller,并创建UserController.java
package com.zk.controller; import org.springframework.stereotype.Controller; @Controller public class UserController { public void execute(){ System.out.println("UserController execute..."); } }
(3)创建com.zk.Service,并创建UserService.java
package com.zk.service; import org.springframework.stereotype.Service; @Service public class UserService { public void add(){ System.out.println("UserService add.."); } }
(4)创建com.zk.Repository,并创建UserRepository.java和UserRepositoryImpl.java
package com.zk.UserRepository; public interface UserRepository { public void save(); }
package com.zk.UserRepository; import org.springframework.stereotype.Repository; @Repository("userRepository") public class UserRepositoryImpl implements UserRepository{ @Override public void save() { // TODO Auto-generated method stub System.out.println("UserRepository save"); } }
(5)最后,实现MainAPP实现类:
MainAPP.java
package Main; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.zk.UserRepository.UserRepository; import com.zk.component.TestObject; import com.zk.controller.UserController; import com.zk.service.UserService; public class MainAPP { public static void main(String[]args) { ApplicationContext ac=new ClassPathXmlApplicationContext("ApplicationContext.xml"); TestObject to=(TestObject) ac.getBean("testObject"); System.out.println(to.toString()); UserService us=(UserService) ac.getBean("userService"); us.add(); UserRepository ur=(UserRepository)ac.getBean("userRepository"); ur.save(); UserController uc=(UserController)ac.getBean("userController"); uc.execute(); } }
ApplicationContext.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: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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <context:component-scan base-package="com.zk.controller" /> <context:component-scan base-package="com.zk.component" /> <context:component-scan base-package="com.zk.UserRepository" /> <context:component-scan base-package="com.zk.service" /> </beans>
执行Main后结果如下:
4. @PostConstruct 和 @PreDestory
实现初始化和销毁bean之前进行的操作,只能有一个方法可以用此注释进行注释,方法不能有参数,返回值必需是void,方法需要是非静态的。
TestObject.java
package com.zk.component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.stereotype.Component; @Component public class TestObject { @PostConstruct public void contructbefore(){ System.out.println("初始化之前的操作"); } @PreDestroy public void contructAfter(){ System.out.println("初始化之后的操作"); } }
MainAPP.java
package Main; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.zk.component.TestObject; public class MainAPP { public static void main(String[]args) { AbstractApplicationContext ac=new ClassPathXmlApplicationContext("ApplicationContext.xml"); TestObject to=(TestObject) ac.getBean("testObject"); System.out.println(to.toString()); ((AbstractApplicationContext) ac).close(); } }
applicationContext.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: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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <context:component-scan base-package="com.zk.component" /> </beans>
执行结果如下:
@PostConstruct:在构造方法和init方法(如果有的话)之间得到调用,且只会执行一次。
@PreDestory:注解的方法在destory()方法调用后得到执行。
引深一点,Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种:
1.通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法;
2.通过 <bean> 元素的 init-method/destroy-method属性指定初始化之后 /销毁之前调用的操作方法;
3.在指定方法上加上@PostConstruct 或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用
但他们之前并不等价。即使3个方法都用上了,也有先后顺序.
Constructor > @PostConstruct >InitializingBean > init-method
5. @Autowired,@Qualifier
@Autowired是用在JavaBean中的注解,默认通过byType形式查找Bean,如果发现多个Bean,则使用byName形式查找Bean,用来给指定的字段或方法注入所需的外部资源。
可以手动使用@Qualifier注解给需要通过byName形式查找的Bean进行赋值,例如
@Autowired @Qualifier(“pean”) public Fruit fruit;
UserDao.java
package com.zk.dao; public interface UserDao { public void sayHello(); }
UserDaoImpl.java
package com.zk.dao; import org.springframework.stereotype.Repository; @Repository("UserDao") public class UserDaoImpl implements UserDao{ public void sayHello(){ System.out.println("userdao hello"); } }
UserService.java
package com.zk.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.zk.dao.UserDao; @Service public class UserService { @Autowired private UserDao userdao; public void sayHello(){ userdao.sayHello(); } }
Main.App
package Main; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.zk.service.UserService; public class MainApp { public static void main(String[]args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService object = (UserService) ctx.getBean("userService"); object.sayHello(); } }
执行MainApp
6. @Primary
(1)首先创建fruit接口,并建立继承fruit接口的两个子类Apple.java,Pear.java,在Pear.java中添加@Primary,将Pear类设为优先。
fruit.java
package com.zk.mybean; import org.springframework.stereotype.Component; public interface fruit { public void sayHello(); }
Apple.java
package com.zk.mybean; import org.springframework.stereotype.Component; @Component public class Apple implements fruit{ public void sayHello(){ System.out.println("Apple Hello"); } }
Pear.java
package com.zk.mybean; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component @Primary public class Pear implements fruit{ public void sayHello(){ System.out.println("Pear Hello"); } }
(2)创建fruitService.java
package com.zk.myservice; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.zk.mybean.fruit; @Service public class fruitService { @Autowired public fruit fruit; public void getfruit(){ fruit.sayHello(); } }
(3)最后,实现MainAPP.java和ApplicationContext.xml
package Main; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.zk.mybean.fruit; import com.zk.myservice.fruitService; public class MainAPP { public static void main(String[]args) { ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); fruitService fs=(fruitService) ac.getBean(fruitService.class); fs.getfruit(); } }
执行结果如下: