spring注解注入示例详解

合集下载

SpringBootApplication注解原理及代码详解

SpringBootApplication注解原理及代码详解

SpringBootApplication注解原理及代码详解1、SpringBoot 启动main()@SpringBootApplicationpublic class TomcatdebugApplication {public static void main(String[] args) {SpringApplication.run(TomcatdebugApplication.class, args);}}1.1 @SpringBootApplication 注解,其实主要是@ComponentScan,@EnableAutoConfiguration,@SpringBootConfiguration三个注解@ComponentScan 注解:spring⾥有四⼤注解:@Service,@Repository,@Component,@Controller⽤来定义⼀个bean.@ComponentScan注解就是⽤来⾃动扫描被这些注解标识的类,最终⽣成ioc容器⾥的bean.可以通过设置@ComponentScan basePackages,includeFilters,excludeFilters属性来动态确定⾃动扫描范围,类型已经不扫描的类型. 默认情况下:它扫描所有类型,并且扫描范围是@ComponentScan注解所在配置类包及⼦包的类@SpringBootConfiguration 注解:@SpringBootConfiguration继承⾃@Configuration,⼆者功能也⼀致,标注当前类是配置类,并会将当前类内声明的⼀个或多个以@Bean注解标记的⽅法的实例纳⼊到spring容器中,并且实例名就是⽅法名。

demo 说明:(1)注⼊spring ioc bean@SpringBootConfigurationpublic class Config {@Beanpublic Map createMap(){Map map = new HashMap();map.put("username","gxz");map.put("age",27);return map;}}(2)调⽤:public static void main( String[] args ){//⽅式1 获取contextConfigurableApplicationContext context = SpringApplication.run(App.class, args);context.getBean(Runnable.class).run();context.getBean("createMap"); //注意这⾥直接获取到这个⽅法beanint age = (int) map.get("age");System.out.println("age=="+age);//⽅式2. 使⽤@Autowired注解,应⽤bean// @Autowired// Map createMap}@EnableAutoConfiguration 注解@EnableAutoConfiguration作⽤:从classpath中搜索所有的META-INF/spring.factories配置⽂件,然后将其中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的value加载到spring容器中。

springboot中@EnableAsync与@Async注解使用

springboot中@EnableAsync与@Async注解使用

springboot中@EnableAsync与@Async注解使⽤springboot中@EnableAsync与@Async注解使⽤@Async为异步注解,放到⽅法上,表⽰调⽤该⽅法的线程与此⽅法异步执⾏,需要配合@EnableAsync注解使⽤。

1、⾸先演⽰没有@Async,即没有异步执⾏的情况- 创建⼀个普通类CountNumber,并注⼊到IOC容器中1 package com.example.demo;2 import org.springframework.scheduling.annotation.Async;3 import ponent;45 @Component6 public class CountNumber {78 public void PrintNumber(){9 for(int i=1; i<10; i++){10 System.out.println("i = " + i);11 }12 }13 }- 在spring boot的启动类中获取IOC的bean1 package com.example.demo;2 import java.util.concurrent.TimeUnit;3 import org.springframework.boot.SpringApplication;4 import org.springframework.boot.autoconfigure.SpringBootApplication;5 import org.springframework.context.ConfigurableApplicationContext;6 import ponentScan;78 //@SpringBootApplication9 @ComponentScan10 public class Springboot3Application {1112 public static void main(String[] args) throws Exception {1314 ConfigurableApplicationContext context = SpringApplication.run(Springboot3Application.class, args);1516 context.getBean(CountNumber.class).PrintNumber();17 for(int i=1; i<10; i++){18 System.out.println("------------------");19 }20 context.close();21 }22 }- 运⾏输出结果:i = 1i = 2i = 3i = 4i = 5i = 6i = 7i = 8i = 9------------------------------------------------------------------------------------------------------------------------------------------------------------------从输出结果中可以看出,启动类先从IOC容器中获取CountNumber的对象,然后执⾏该对象的PrintNumber⽅法,循环打印了9个数字,⽅法执⾏结束后,继续回到启动类中往下执⾏,因此开始执⾏for循环语句。

Spring注解【非单例】

Spring注解【非单例】

Spring注解【⾮单例】花了⾄少⼀整天的时间解决了这个问题,必须记录这个纠结的过程,问题不可怕,思路很绕弯。

为了能说清楚⾃⼰的问题,我都⽤例⼦来模拟。

我有⼀个类MyThread是这样的:1 @Service2public class MyThread extends Thread {3 @Autowired4 MyService myService;5 ......6 }在主线程中有这样⼀个调⽤:1 @Autowired2 MyThread myThread;3 ......4public void invoke{5if(condition){6 myThread.start();7 }8 }9 ......我的invoke存在⼀个循环调⽤,此时遇到了第⼀个问题!问题⼀:抛出ng.IllegalThreadStateException。

问题⼀的解决:1//@Autowired2//MyThread myThread;3 ......4public void invoke {5if(condition){6 //myThread.start();6 MyThread myThread = new MyThread();7 myThread.start();8 }9 }引发的新的问题!问题⼆:我⽤了Spring注解,⽤new的话⽆法⽤注解实现注⼊,所以myThread中的myService对象抛出空指针。

问题⼆的解决:放弃了MyThread类,新写了⼀个类,开始绕弯。

1 @Service2public class MyRunable implements Runnable {3 @Autowired4 MyService myService;5 ......6 }相应的,修改主线程中的调⽤。

1//@Autowired2//MyThread myThread;3 @Autowired4 MyRunnable myRunnable;5 ......6public void invoke{7if(condition){8//MyThread myThread = new MyThread();9//myThread.start();10 Thread t = new Thread(myRunnable);11 t.start();12 }13 }14 ......⼜遇到了新的问题!我需要对myRunnable线程命名。

Spring为什么不推荐使用@Autowired注解详析

Spring为什么不推荐使用@Autowired注解详析

Spring为什么不推荐使⽤@Autowired注解详析⽬录引⾔Spring的三种注⼊⽅式属性(filed)注⼊构造器注⼊set⽅法注⼊属性注⼊可能出现的问题问题⼀问题⼆问题三spring建议使⽤@Resource代替@Autowired使⽤@RequiredArgsConstructor构造器⽅式注⼊总结引⾔使⽤IDEA开发时,同组⼩伙伴都喜欢⽤@Autowired注⼊,代码⼀⽚warning,看着很不舒服,@Autowired作为Spring的亲⼉⼦,为啥在IDEA中提⽰了⼀个警告:Field injection is not recommended想搞清楚这个问题之前,⾸先先了解⼀下依赖注⼊的⼏种⽅式Spring的三种注⼊⽅式属性(filed)注⼊这种注⼊⽅式就是在bean的变量上使⽤注解进⾏依赖注⼊。

本质上是通过反射的⽅式直接注⼊到field。

这是我平常开发中看的最多也是最熟悉的⼀种⽅式。

@AutowiredUserDao userDao;构造器注⼊将各个必需的依赖全部放在带有注解构造⽅法的参数中,并在构造⽅法中完成对应变量的初始化,这种⽅式,就是基于构造⽅法的注⼊。

⽐如:finalUserDao userDao;@Autowiredpublic UserServiceImpl(UserDao userDao) {erDao = userDao;}set⽅法注⼊通过对应变量的setXXX()⽅法以及在⽅法上⾯使⽤注解,来完成依赖注⼊。

⽐如:private UserDao userDao;@Autowiredpublic void setUserDao (UserDao userDao) {erDao = userDao;}属性注⼊可能出现的问题问题⼀基于 field 的注⼊可能会带来⼀些隐含的问题。

来我们举个例⼦:@Autowiredprivate User user;private String company;public UserDaoImpl(){pany = user.getCompany();}编译过程不会报错,但是运⾏之后报NullPointerExceptionInstantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [...]: Constructor threw exception; nested exception is ng.NullPointerExceptionJava 在初始化⼀个类时,是按照静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造⽅法 -> @Autowired 的顺序。

SpringAOP示例与实现原理总结——传统springaop、基于切面注入、基于@Asp。。。

SpringAOP示例与实现原理总结——传统springaop、基于切面注入、基于@Asp。。。

SpringAOP⽰例与实现原理总结——传统springaop、基于切⾯注⼊、基于@Asp。

⼀、代码实践1)经典的Spring Aop经典的spring aop,是基于动态代理技术的。

实现⽅式上,最常⽤的是实现MethodInterceptor接⼝来提供环绕通知,创建若⼲代理,然后使⽤ProxyBeanFactory配置⼯⼚bean,⽣成拦截器链,完成拦截。

⽰例如下:1package demo.spring;23import org.aopalliance.intercept.MethodInterceptor;4import org.aopalliance.intercept.MethodInvocation;5import org.junit.Test;6import org.junit.runner.RunWith;7import org.springframework.beans.factory.annotation.Autowired;8import org.springframework.test.context.ContextConfiguration;9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;1011 @RunWith(SpringJUnit4ClassRunner.class)12 @ContextConfiguration("classpath:spring-config.xml")13public class TraditionalSpringAopDemo {14 @Autowired15private Service proxy;1617 @Test18public void test() {19 proxy.execute("hello world!");20 }21 }2223interface Service {24void execute(String str);25 }2627class ServiceImpl implements Service {28 @Override29public void execute(String str) {30 System.out.println("execute invoke: " + str);31 }32 }3334class Interceptor1 implements MethodInterceptor {35 @Override36public Object invoke(MethodInvocation methodInvocation) throws Throwable {37 System.out.println("interceptor1,before invoke");38 Object ret = methodInvocation.proceed();39 System.out.println("interceptor1,after invoke");40return ret;41 }42 }4344class Interceptor2 implements MethodInterceptor {45 @Override46public Object invoke(MethodInvocation methodInvocation) throws Throwable {47 System.out.println("interceptor2,before invoke");48 Object ret = methodInvocation.proceed();49 System.out.println("interceptor2,after invoke");50return ret;51 }52 }xml⽂件配置:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:context="/schema/context"5 xmlns:aop="/schema/aop"6 xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/sprin 78<context:component-scan base-package="demo.spring"/>910<bean class="demo.spring.ServiceImpl" id="service"></bean>11<bean class="demo.spring.Interceptor1" id="interceptor1"></bean>12<bean class="demo.spring.Interceptor2" id="interceptor2"></bean>13<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy">14<property name="target" ref="service"/>15<property name="interceptorNames">16<list>17<value>interceptor1</value>18<value>interceptor2</value>19</list>20</property>21</bean>22</beans>结果:interceptor1,before invokeinterceptor2,before invokeexecute invoke: hello world!interceptor2,after invokeinterceptor1,after invoke可以看到拦截链的执⾏过程与拦截器顺序的关系。

springboot使用自定义注解注入参数值

springboot使用自定义注解注入参数值

springboot使用自定义注解注入参数值在Spring Boot中,我们可以使用自定义注解来注入参数值,以简化代码编写和提高可读性。

通过自定义注解,我们可以将一些通用的参数值注入到方法中,而不需要重复的代码。

```javaimport ng.annotation.*;String value(;```接下来,我们需要创建一个注解处理器来实现参数的注入逻辑。

我们可以使用Spring Boot提供的接口HandlerMethodArgumentResolver,并实现其中的resolveArgument和supportsParameter方法。

```javaimport org.springframework.core.MethodParameter;importorg.springframework.web.bind.support.WebDataBinderFactory;importorg.springframework.web.context.request.NativeWebRequest;importorg.springframework.web.method.support.HandlerMethodArgumentReso lver;importorg.springframework.web.method.support.ModelAndViewContainer;public class CustomValueArgumentResolver implements HandlerMethodArgumentResolverpublic boolean supportsParameter(MethodParameter parameter) returnparameter.getParameterAnnotation(CustomValue.class) != null;}public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws ExceptionCustomValue customValue =parameter.getParameterAnnotation(CustomValue.class);String value = customValue.value(;return value;}```最后,我们需要配置Spring Boot,以便它能够使用我们自定义的注解处理器。

SpringCloud之@FeignClient()注解的使用方式

SpringCloud之@FeignClient()注解的使用方式

SpringCloud之@FeignClient()注解的使⽤⽅式⽬录@FeignClient()注解的使⽤@FeignClient标签的常⽤属性如下SpringCloud服务间互相调⽤@FeignClient注解我在FEIGN-CONSUMER在FEIGN-CONSUMER这是项⽬中的Controller层@FeignClient()注解的使⽤由于SpringCloud采⽤分布式微服务架构,难免在各个⼦模块下存在模块⽅法互相调⽤的情况。

⽐如service-admin服务要调⽤service-card 服务的⽅法。

@FeignClient()注解就是为了解决这个问题的。

@FeignClient()注解的源码要求它必须在Interface接⼝上使⽤。

( FeignClient注解被@Target(ElementType.TYPE)修饰,表⽰FeignClient注解的作⽤⽬标在接⼝上)@RequestLine与其它请求不同,只需要简单写请求⽅式和路径就能达到请求其它服务的⽬的。

@FeignClient(value = "feign-server",configuration = FeignConfig.class) //需要⼀个配置⽂件public interface TestService {@RequestLine("POST /feign/test") //对应请求⽅式和路径String feign(@RequestBody UserDO userDO);}@EnableFeignClients@SpringBootConfigurationpublic class FeignConfig {@Beanpublic Contract contract(){return new feign.Contract.Default();}}@FeignClient标签的常⽤属性如下value: 服务名name: 指定FeignClient的名称,如果项⽬使⽤了Ribbon,name属性会作为微服务的名称,⽤于服务发现url: url⼀般⽤于调试,可以⼿动指定@FeignClient调⽤的地址decode404:当发⽣http 404错误时,如果该字段位true,会调⽤decoder进⾏解码,否则抛出FeignExceptionconfiguration: Feign配置类,可以⾃定义Feign的Encoder、Decoder、LogLevel、Contractfallback: 定义容错的处理类,当调⽤远程接⼝失败或超时时,会调⽤对应接⼝的容错逻辑,fallback指定的类必须实现@FeignClient标记的接⼝fallbackFactory: ⼯⼚类,⽤于⽣成fallback类⽰例,通过这个属性我们可以实现每个接⼝通⽤的容错逻辑,减少重复的代码path: 定义当前FeignClient的统⼀前缀此外还要求服务的启动类要有@EnableFeignClients 注解才能使Fegin⽣效。

Springboot中@Value的使用详解

Springboot中@Value的使用详解

Springboot中@Value的使⽤详解Springboot通过@Value注解将配置⽂件中的属性注⼊到容器内组件中(可⽤在@Controller、@Service、@Configuration、@Component等Spring托管的类中)1.普通字符串注⼊例:yml中存在key:name: zs@Value注⼊@Value("${name}")public String name;当yml中的name没有对应值时,即yml中为:name:此时字符串name的值为""可设置注⼊属性的默认值(当配置⽂件中没有此key时,此默认值⽣效),语法:@Value("${name:zch}")public String name;// 此时,若配置⽂件中没有name这个key,变量name的值为zch2.常⽤的int、boolean类型例:yml中存在key:port: 8888flag: true@Value注⼊@Value("${port}")public int port;@Value("${flag}")public boolean flag;3.数组类型例:yml中存在key:id: 1,2,3@Value注⼊@Value("${id}")public int[] idArray;当yml中id没有对应值时,数组idArray为⾮null空数组,长度为04.list类型例:yml中存在key:id: 1,2,3@Value注⼊@Value("#{'${id}'.split(',')}")public List<String> idList;当yml中id没有对应值时,集合idList长度为1,存在值"" (原本以为是空集合,造成bug,特记录) 5.map类型例:yml中存在key:user: "{name: 'zs',age: '23'}" #注意此值⽤双引号包裹@Value注⼊@Value("#{${user}}")public Map<String,String> userInfo;当yml中user没有对应值是,启动报错#{}表⽰使⽤SpEL表达式,(此处是来⾃未来的⽂章超链接,正在路上)以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

qualifier注解的使用方法

qualifier注解的使用方法

qualifier注解的使用方法
Qualifier注解是Spring中常用的一种注解,它用于解决自动注入时出现多个类型相同的Bean时,无法确定注入哪一个Bean的问题。

本文就Qualifier注解的使用方法进行详细地讲解。

Qualifier注解是Spring框架中的注解,用于配合自动注入完成特定bean的注入操作。

在Spring容器中,可以存在多个类型相同的Bean,很容易在自动装配时出现混淆问题。

为了解决这一问题,Spring中提供了Qualifier注解。

Qualifier注解指定按名称注入,即指定名称与指定类型注入匹配。

当容器中存在多个相同类型的Bean时,我们可以使用Qualifier注解指定名称来完成注入操作。

使用方法如下:
- 1、首先,在需要注入的位置使用Autowired注解,在其中指定Qualifier注解的value属性,即需要注入的Bean的名称,形式如下:
```
@Autowired
@Qualifier("beanName")
private BeanType bean;
```
- 2、在需要注入到的Bean上,使用Component注解或其他Spring框架支持的Bean 管理注解来指定Bean的名称,如下示例:
当容器中有多个相同类型的Bean时,如果没有指定Qualifier注解的value属性,会抛出异常,如下示例:
当指定Qualifier注解的value属性后,Spring会按照名称与类型进行匹配,选择合适的Bean进行注入操作,并将对应名称的Bean注入到需要注入BeanType类型的位置上。

nestedconfigurationproperty注解

nestedconfigurationproperty注解

`@NestedConfigurationProperty` 注解是Spring Boot 中用于处理嵌套配置属性的注解。

它通常用于将一个配置属性的值注入到一个嵌套的对象中。

这个注解的主要作用是将一个外部的配置属性值映射到内部对象的相应属性上。

使用`@NestedConfigurationProperty` 注解时,需要指定以下三个属性:1. `prefix`:外部配置属性的前缀,用于区分不同的配置属性。

2. `value`:内部对象的属性名,用于将外部配置属性值注入到该属性上。

3. `nestedProperties`:一个字符串数组,用于指定内部对象中需要注入外部配置属性的其他属性名。

下面是一个简单的示例:```javaimport org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.context.properties.NestedConfigurationProperty;ConfigurationProperties(prefix = "myconfig")public class MyConfig {private String name;private NestedConfig nestedConfig;// getter and setter methods}class NestedConfig {private String nestedName;private String nestedValue;// getter and setter methods}```在这个示例中,我们定义了一个名为`MyConfig` 的配置类,并使用`@ConfigurationProperties` 注解指定了前缀为"myconfig"。

Spring中Bean管理的常用注解

Spring中Bean管理的常用注解

Spring中Bean管理的常⽤注解在Spring中,主要⽤于管理bean的注解分为四⼤类:1.⽤于创建对象。

2.⽤于给对象的属性注⼊值。

3.⽤于改变作⽤的范围。

4.⽤于定义⽣命周期。

这⼏个在开发中经常接触到,也可以说每天都会遇见。

其中创建对象是重点,Spring中创建对象的有四个:分别是@Component,@Controller,@Service,@Repository。

对于@Component注解:把资源让Spring来管理,相当于xml中的配置的Bean。

属性:value:指定Bean中的id。

如果不指定value属性,默认Bean的id是当前类的类名,⾸字母⼩写。

在开发中的场景是这样的,其实是在实现类中加⼊即可:@Component("customerService")public class CustomerServiceImpl implements CustomerService{public void save() {System.out.println("顾客保存⽅法");}}⽽其它的三个注解都是针对⼀个衍⽣注解,它们的作⽤及属性都是⼀模⼀样的。

只不过提供了更加明确的语义化。

@Controller:⼀般⽤于表现层的注解。

@Service:⼀般⽤于业务层的注解。

@responsitory:⼀般⽤于持久层的注解。

⽤法与以上相同,这⾥不做过多的解释。

要理解这个三个注解就是让标注类本⾝的⽤途清晰⽽已。

接下来,聊聊⽤于给对象的属性注⼊值得问题。

Spring给我们提出了注⼊数据的注解有:@Value,@Autowired,@Qualifier,@Resource。

其中@Value:注⼊基本数据类型和String类型数据,它的属性value⽤于指定值。

@Autowired这个⽤法是⽐较重要的,它能够⾃动按照类型注⼊。

当使⽤注解注⼊属性时,set⽅法可以省略。

JavaSpring@Lazy延迟注入源码案例详解

JavaSpring@Lazy延迟注入源码案例详解

JavaSpring@Lazy延迟注⼊源码案例详解前⾔有时候我们会在属性注⼊的时候添加@Lazy注解实现延迟注⼊,今天咱们通过阅读源码来分析下原因⼀、⼀个简单的⼩例⼦代码如下:@Servicepublic class NormalService1 {@Autowired@Lazyprivate MyService myService;public void doSomething() {myService.getName();}}作⽤是为了进⾏延迟加载,在NormalService1进⾏属性注⼊的时候,如果MyService还没有⽣成bean也不⽤担⼼,会注⼊⼀个代理,但是在实际运⾏的时候,会获取Spring容器中实际的MyService,在某些情况下,因为spring⽣命周期的原因,这个注解有⼤⽤。

⼆、源码解读1. 注⼊代码如下(DefaultListableBeanFactory#resolveDependency):public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {//如果注⼊属性添加了@Lazy,懒加载,此时spring会根据具体类型搞个cglib代理类Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}很明显要执⾏getLazyResolutionProxyIfNecessary⽅法,如果加了@Lazy注解,最终会执⾏buildLazyResolutionProxy⽅法protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,"BeanFactory needs to be a DefaultListableBeanFactory");final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return descriptor.getDependencyType();}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);/**something valid**/return target;}@Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf = new ProxyFactory();pf.setTargetSource(ts);Class<?> dependencyType = descriptor.getDependencyType();if (dependencyType.isInterface()) {pf.addInterface(dependencyType);}return pf.getProxy(beanFactory.getBeanClassLoader());}可以看到上⾯这段代码,其实就是⽣成了⼀个TargetSource,然后再⽣成了⼀个代理(CGLIB或者JDK),然后作为MyService对象注⼊给了NormalService1。

SpringBoot注解解析大全(非常全哦!)

SpringBoot注解解析大全(非常全哦!)

SpringBoot注解解析⼤全(⾮常全哦!)使⽤注解的优势:1.采⽤纯java代码,不在需要配置繁杂的xml⽂件2.在配置中也可享受⾯向对象带来的好处3.类型安全对重构可以提供良好的⽀持4.减少复杂配置⽂件的同时亦能享受到springIoC容器提供的功能⼀、注解详解(配备了完善的释义)------(可采⽤ctrl+F 来进⾏搜索哦~~~~也可以收藏⽹页这样以后就不⽤往复查询了哦)@SpringBootApplication:申明让spring boot⾃动给程序进⾏必要的配置,这个配置等同于:@Configuration ,@EnableAutoConfiguration 和 @ComponentScan 三个配置。

@ResponseBody:表⽰该⽅法的返回结果直接写⼊HTTP response body中,⼀般在异步获取数据时使⽤,⽤于构建RESTful的api。

在使⽤@RequestMapping后,返回值通常解析为跳转路径,加上@esponsebody后返回结果不会被解析为跳转路径,⽽是直接写⼊HTTP response body中。

⽐如异步获取json数据,加上@Responsebody后,会直接返回json数据。

该注解⼀般会配合@RequestMapping⼀起使⽤。

@Controller:⽤于定义控制器类,在spring项⽬中由控制器负责将⽤户发来的URL请求转发到对应的服务接⼝(service层),⼀般这个注解在类中,通常⽅法需要配合注解@RequestMapping。

@RestController:⽤于标注控制层组件(如struts中的action),@ResponseBody和@Controller的合集。

@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。

@EnableAutoConfiguration:SpringBoot⾃动配置(auto-configuration):尝试根据你添加的jar依赖⾃动配置你的Spring应⽤。

SpringBoot自定义注解实现后台接收Json参数

SpringBoot自定义注解实现后台接收Json参数

SpringBoot自定义注解实现后台接收Json参数Spring Boot是一个用于构建独立的、基于生产级别的Java应用程序的框架。

它使得开发人员可以轻松地创建具有高效、可靠和可扩展特性的Spring应用程序。

在Spring Boot中,我们可以使用自定义注解来处理后台接收JSON参数的需求。

```javaimport org.springframework.web.bind.annotation.RequestBody;import ng.annotation.ElementType;import ng.annotation.Retention;import ng.annotation.RetentionPolicy;import ng.annotation.Target;```接下来,我们可以在Spring Boot的Controller中使用这个自定义注解来接收JSON参数。

下面是一个简单的例子:```javaimport org.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RestController;public class UserController//处理用户添加的逻辑}```需要注意的是,为了使Spring Boot能够正确地将请求体中的JSON 数据转换为Java对象,我们需要在项目中引入相关的依赖。

可以在`pom.xml`文件中添加以下依赖:```xml<dependency><artifactId>jackson-databind</artifactId></dependency>```这个依赖将提供JSON与Java对象之间的转换功能。

总结来说,Spring Boot的自定义注解可以很方便地实现后台接收JSON参数的功能。

SpringBoot使用自定义注解实现权限拦截的示例

SpringBoot使用自定义注解实现权限拦截的示例

SpringBoot使⽤⾃定义注解实现权限拦截的⽰例本⽂介绍了SpringBoot使⽤⾃定义注解实现权限拦截的⽰例,分享给⼤家,具体如下:HandlerInterceptor(处理器拦截器)常见使⽤场景⽇志记录: 记录请求信息的⽇志, 以便进⾏信息监控, 信息统计, 计算PV(page View)等性能监控:权限检查:通⽤⾏为:使⽤⾃定义注解实现权限拦截⾸先HandlerInterceptor了解在HandlerInterceptor中有三个⽅法:public interface HandlerInterceptor {// 在执⾏⽬标⽅法之前执⾏boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception;// 执⾏⽬标⽅法之后执⾏void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;// 在请求已经返回之后执⾏void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;}在以上注释中已经写明执⾏顺序, 测试及测试结果如下:public class TestInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandler");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandler");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion");}}结果:preHandlerpostHandlerafterCompletion如何配置拦截器后⾯讲:下⾯来讲讲这个拦截器是拦截的什么?⽅法拦截器HandlerInterceptor我们使⽤SpringMVC都知道SpringMVC是基于⽅法的请求处理, 和Struts2有明显区别(我是这么理解的), 并且Controller是单例模式, 所有请求都是从DispatcherServlet来调⽤请求url对应的⽅法的(处理器映射器的功能), 那么它是⼀个⽅法拦截器, 如何知道呢?@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(handler.getClass());return true;}执⾏结果:class org.springframework.web.method.HandlerMethod已经看到拦截器如何⼯作, 并且知道它是⽅法级别的拦截器, 那么接下来看看如何配置拦截器, 让它在服务器运⾏期间起作⽤实现HandlerInterceptor实现HandlerInterceptor接⼝或者继承HandlerInterceptorAdapter类HandlerInterceptorAdapter适配器是对HandlerInterceptor接⼝做了默认实现, 这种适配器模式, 是为了⽅便开发者只去想要复写⽅法, 其他⽅法采取默认措施.上⾯的TestInterceptor就是⼀个Demo, 具体可以按需求在我们想要拦截的位置进⾏相应的逻辑处理配置拦截器从Spring4.x开始, 就⽀持注解配置具体是使⽤@Configuration注解标注⼀个普通类, 使该类成为配置类, 可以在该类中定义Bean, 以及注⼊⼀些配置参数等.⾸先, 我们要配置拦截器,就需要想SpringMvc的拦截链中取注⼊我们的拦截器, 这样才能请求进来时去拦截我们想要拦截的请求, 所以, 需要我们新建⼀个普通类, 使⽤@Configuration注解标注在类名上, 并且让该类继承WebMvcConfigurerAdapter,为什么不实现WebMvcConfigurer接⼝呢? 因为⽅法太多,我们不需要复写其中所有⽅法...下⾯让我们新建⼀个配置类, 来配置我们的拦截器@Configurationpublic class InterceptorConfig extends WebMvcConfigurerAdapter {public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");}}复写addInterceptors之后, 当我们的服务器启动时, 会⾃动调⽤这个⽅法, 参数怎么传我们都不⽤管(⽬前是java初级阶段, 没空研究Spring深层原理), 我们只要知道这个⽅法⼀定会被调⽤就⾏了.我们直接new⼀个⾃定义拦截器, 注册到整个拦截链中, 并且制定拦截路径, 这样当满⾜请求url拦截配置时, 我们的⾃定义拦截器就会执⾏相应的⽅法了.拦截⽅法是⾮常灵的, 除了拦截配置的, 也可以拦截⾮匹配的, 也可以根据正则表达式拦截请求⾄此, 我们的拦截器就完成了, 接下来⾃定义权限相关注解⾃定义权限注解定义⼀个@interface类@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Access {String[] value() default {};String[] authorities() default {};String[] roles() default {};}@Target注解是标注这个类它可以标注的位置:常⽤的元素类型(ElementType):public enum ElementType {/** Class, interface (including annotation type), or enum declaration */// TYPE类型可以声明在类上或枚举上或者是注解上TYPE,/** Field declaration (includes enum constants) */// FIELD声明在字段上FIELD,/** Method declaration */// 声明在⽅法上METHOD,/** Formal parameter declaration */// 声明在形参列表中PARAMETER,/** Constructor declaration */// 声明在构造⽅法上CONSTRUCTOR,/** Local variable declaration */// 声明在局部变量上LOCAL_VARIABLE,/** Annotation type declaration */ANNOTATION_TYPE,/** Package declaration */PACKAGE,/*** Type parameter declaration** @since 1.8*/TYPE_PARAMETER,/*** Use of a type** @since 1.8*/TYPE_USE}@Retention注解表⽰的是本注解(标注这个注解的注解保留时期)public enum RetentionPolicy {/*** Annotations are to be discarded by the compiler.*/// 源代码时期SOURCE,/*** Annotations are to be recorded in the class file by the compiler* but need not be retained by the VM at run time. This is the default* behavior.*/// 字节码时期, 编译之后CLASS,/*** Annotations are to be recorded in the class file by the compiler and* retained by the VM at run time, so they may be read reflectively.** @see ng.reflect.AnnotatedElement*/// 运⾏时期, 也就是⼀直保留, 通常也都⽤这个RUNTIME}@Documented是否⽣成⽂档的标注, 也就是⽣成接⼝⽂档是, 是否⽣成注解⽂档注解说完了, 下⾯需要到对应的controller的⽅法中取添加注解, 配置该⽅法允许的权限在⽅法上配置权限@RestControllerpublic class HelloController {@RequestMapping(value = "/admin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET) // 配置注解权限, 允许⾝份为admin, 或者说允许权限为admin的⼈访问@Access(authorities = {"admin"})public String hello() {return "Hello, admin";}}编写权限逻辑// ⾃定义⼀个权限拦截器, 继承HandlerInterceptorAdapter类public class AuthenticationInterceptor extends HandlerInterceptorAdapter {// 在调⽤⽅法之前执⾏拦截@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 将handler强转为HandlerMethod, 前⾯已经证实这个handler就是HandlerMethodHandlerMethod handlerMethod = (HandlerMethod) handler;// 从⽅法处理器中获取出要调⽤的⽅法Method method = handlerMethod.getMethod();// 获取出⽅法上的Access注解Access access = method.getAnnotation(Access.class);if (access == null) {// 如果注解为null, 说明不需要拦截, 直接放过return true;}if (access.authorities().length > 0) {// 如果权限配置不为空, 则取出配置值String[] authorities = access.authorities();Set<String> authSet = new HashSet<>();for (String authority : authorities) {// 将权限加⼊⼀个set集合中authSet.add(authority);}// 这⾥我为了⽅便是直接参数传⼊权限, 在实际操作中应该是从参数中获取⽤户Id// 到数据库权限表中查询⽤户拥有的权限集合, 与set集合中的权限进⾏对⽐完成权限校验String role = request.getParameter("role");if (StringUtils.isNotBlank(role)) {if (authSet.contains(role)) {// 校验通过返回true, 否则拦截请求return true;}}}// 拦截之后应该返回公共结果, 这⾥没做处理return false;}}⾄此, 我们启动服务器, 访问接⼝, 就能看到效果, 这⾥不做⽰范了以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

spring使用注解通过子类注入父类的私有变量

spring使用注解通过子类注入父类的私有变量

spring使⽤注解通过⼦类注⼊⽗类的私有变量⽅法⼀通过 super.setBaseDao⽅法设置⽗类私有变量⽗类public class BaseServiceImpl {private BaseDao baseDao;public BaseDao getBaseDao() {return baseDao;}public void setBaseDao(BaseDao baseDao) {this.baseDao = baseDao;}public void test(){System.out.println("TsetService...... ");baseDao.test();}}⼦类@Service("testServiceImpl")public class TestServiceImpl extends BaseServiceImpl{@Resource(name="testDao")public void initBaseDao(TestDao testDao) {super.setBaseDao(testDao);}}⽅法⼆@PostConstruct是Java EE 5引⼊的注解,Spring允许开发者在受管Bean中使⽤它。

当DI容器实例化当前受管Bean时,@PostConstruct注解的⽅法会被⾃动触发,从⽽完成⼀些初始化⼯作⽗类同上⼦类@Service("testServiceImpl")public class TestServiceImpl extends BaseServiceImpl{private TestDao testDao;public TestDao getTestDao() {return testDao;}@Resource(name="testDao")public void setTestDao(TestDao testDao) {this.testDao = testDao;}@PostConstructpublic void initBaseDao(TestDao testDao) {super.setBaseDao(testDao);}}⽅法三⽗类被注⼊对象⾮私有,⼦类重写setter⽅法注⼊到⽗类变量⽗类public class BaseServiceImpl {protected BaseDao baseDao;public BaseDao getBaseDao() {return baseDao;}public void setBaseDao(BaseDao baseDao) {this.baseDao = baseDao;}public void test(){System.out.println("TsetService...... ");baseDao.test();}}⼦类@Service("testServiceImpl")public class TestServiceImpl extends BaseServiceImpl{@Resource(name="testDao")public void setBaseDao(BaseDao baseDao) {this.baseDao = baseDao;}}。

autowired注解 单例

autowired注解 单例

autowired注解单例
`@Autowired` 注解是Spring框架中的注解之一,用于依赖注入。

当我们在一个类中使用`@Autowired` 注解标注一个字段或者构造器时,Spring会根据类型自动将对应的依赖注入到这个字段或者构造器中。

而单例是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点。

在Spring中,默认情况下,使用`@Autowired` 注解注入的bean是单例的,也就是说,在整个应用程序中只会创建一个该类型的实例,并且所有的依赖都会共享这个实例。

下面是一个示例:
```java
@Service
public class MyService {
private MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
// ...
}
```
在上面的例子中,`MyService` 类中的`myRepository` 字段被`@Autowired` 注解标注,Spring会自动将`MyRepository` 类型的实例注入到这个字段中。

由于默认情况下,Spring创建的bean是单例的,所以在整个应用程序中只会创建一个`MyRepository` 类型的实例,并且这个实例会被共享给所有需要依赖注入的地方。

Spring如何利用@Value注解读取yml中的map配置

Spring如何利用@Value注解读取yml中的map配置

Spring如何利⽤@Value注解读取yml中的map配置⽬录@Value注解读取yml中的map配置下边是我在yml中的map写法使⽤时候注解的写法举个例⼦spring注解@Value通过yml⽂件注⼊mapyml⽂件java代码注⼊@Value注解读取yml中的map配置⽹上查了好多资料,都是.properties⽂件中读取,⽽且⼜是⼏个⼈抄来抄去,找了半天功夫不负有⼼⼈,终于找到了详尽的⽤法介绍。

下边是我在yml中的map写法test:map: '{"test1":"12345","test2":"54321"}'使⽤时候注解的写法@Value("#{${test.map}}")private Map<String,String> mapKey;如果是.properties⽂件写法很不⼀样。

还有⼀种使⽤⽅法时创建⼀个类,使⽤@ConfigurationProperties注解,举个例⼦yml⽂件的写法:test:map:key1: 12345key2: 54321新建类的写法:package com.sohu.umab.backendoperation.vo;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import ponent;import java.util.HashMap;import java.util.Map;@Data@Component@ConfigurationProperties(prefix = "test")public class AppKey {//此处属性名必须和yml⽂件中的保持⼀致,否则读取不到private Map map = new HashMap();}然后在使⽤的地⽅,直接注⼊你创建的类即可,这种⽅法缺点就是,之后每增加⼀个配置map,你就需要改这个类,耦合性⾼,不太灵活,推荐使⽤注解的⽅式。

springboot@ConditionalOnMissingBean注解的作用详解

springboot@ConditionalOnMissingBean注解的作用详解

springboot@ConditionalOnMissingBean注解的作⽤详解@ConditionalOnMissingBean,它是修饰bean的⼀个注解,主要实现的是,当你的bean被注册之后,如果⽽注册相同类型的bean,就不会成功,它会保证你的bean只有⼀个,即你的实例只有⼀个,当你注册多个相同的bean时,会出现异常,以此来告诉开发⼈员。

代码演⽰@Componentpublic class AutoConfig {@Beanpublic AConfig aConfig() {return new AConfig("lind");}@Bean@ConditionalOnMissingBean(AMapper.class)public AMapper aMapper1(AConfig aConfig) {return new AMapperImpl1(aConfig);}@Beanpublic AMapper aMapper2(AConfig aConfig) {return new AMapperImpl2(aConfig);}}因为在aMapper1上⾯标识了AMapper类型的bean只能有⼀个实现 @ConditionalOnMissingBean(AMapper.class),所以在进⾏aMapper2注册时,系统会出现上⾯图上的异常,这是正常的。

当我们把 @ConditionalOnMissingBean(AMapper.class) 去掉之后,你的bean可以注册多次,这时需要⽤的@Primary来确定你要哪个实现;⼀般来说,对于⾃定义的配置类,我们应该加上@ConditionalOnMissingBean注解,以避免多个配置同时注⼊的风险。

@Primary标识哪个是默认的bean@Beanpublic AMapper aMapper1(AConfig aConfig) {return new AMapperImpl1(aConfig);}@Bean@Primarypublic AMapper aMapper2(AConfig aConfig) {return new AMapperImpl2(aConfig);}@ConditionalOnProperty通过其三个属性prefix,name以及havingValue来实现的,其中prefix表⽰配置⽂件⾥节点前缀,name⽤来从application.properties中读取某个属性值,havingValue表⽰⽬标值。

使用Springboot自定义注解,支持SPEL表达式

使用Springboot自定义注解,支持SPEL表达式

使⽤Springboot⾃定义注解,⽀持SPEL表达式⽬录Springboot⾃定义注解,⽀持SPEL表达式1.⾃定义注解2.使⽤AOP拦截⽅法,解析注解参数⾃定义注解结合切⾯和spel表达式⾃定义⼀个注解⾃定义⼀个service类,在需要拦截的⽅法上加上@Log注解写⼀个⾃定义切⾯pom⽂件的依赖测试增加内容Springboot⾃定义注解,⽀持SPEL表达式举例,⾃定义redis模糊删除注解1.⾃定义注解import ng.annotation.ElementType;import ng.annotation.Retention;import ng.annotation.RetentionPolicy;import ng.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface CacheEvictFuzzy {/*** redis key集合,模糊删除* @return*/String[] key() default "";}2.使⽤AOP拦截⽅法,解析注解参数import ng3.StringUtils;import ng.ProceedingJoinPoint;import ng.annotation.AfterThrowing;import ng.annotation.Around;import ng.annotation.Aspect;import ng.annotation.Pointcut;import ng.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.LocalVariableTableParameterNameDiscoverer;import org.springframework.core.annotation.Order;import org.springframework.expression.ExpressionParser;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import ponent;import ng.reflect.Method;import java.util.Set;@Aspect@Order(1)@Componentpublic class CacheCleanFuzzyAspect {Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate RedisUtil redis;//指定要执⾏AOP的⽅法@Pointcut(value = "@annotation(cacheEvictFuzzy)")public void pointCut(CacheEvictFuzzy cacheEvictFuzzy){}// 设置切⾯为加有 @RedisCacheable注解的⽅法@Around("@annotation(cacheEvictFuzzy)")public Object around(ProceedingJoinPoint proceedingJoinPoint, CacheEvictFuzzy cacheEvictFuzzy){return doRedis(proceedingJoinPoint, cacheEvictFuzzy);}@AfterThrowing(pointcut = "@annotation(cacheEvictFuzzy)", throwing = "error")public void afterThrowing (Throwable error, CacheEvictFuzzy cacheEvictFuzzy){logger.error(error.getMessage());}/*** 删除缓存* @param proceedingJoinPoint* @param cacheEvictFuzzy* @return*/private Object doRedis (ProceedingJoinPoint proceedingJoinPoint, CacheEvictFuzzy cacheEvictFuzzy){Object result = null;//得到被切⾯修饰的⽅法的参数列表Object[] args = proceedingJoinPoint.getArgs();// 得到被代理的⽅法Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();String[] keys = cacheEvictFuzzy.key();Set<String> keySet = null;String realkey = "";for (int i = 0; i < keys.length; i++) {if (StringUtils.isBlank(keys[i])){continue;}realkey = parseKey(keys[i], method, args);keySet = redis.keys("*"+realkey+"*");if (null != keySet && keySet.size()>0){redis.delKeys(keySet);logger.debug("拦截到⽅法:" + proceedingJoinPoint.getSignature().getName() + "⽅法");logger.debug("删除的数据key为:"+keySet.toString());}}try {result = proceedingJoinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}finally {return result;}* key 定义在注解上,⽀持SPEL表达式* @return*/private String parseKey(String key, Method method, Object [] args){if(StringUtils.isEmpty(key)) return null;//获取被拦截⽅法参数名列表(使⽤Spring⽀持类库)LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paraNameArr = u.getParameterNames(method);//使⽤SPEL进⾏key的解析ExpressionParser parser = new SpelExpressionParser();//SPEL上下⽂StandardEvaluationContext context = new StandardEvaluationContext();//把⽅法参数放⼊SPEL上下⽂中for(int i=0;i<paraNameArr.length;i++){context.setVariable(paraNameArr[i], args[i]);}return parser.parseExpression(key).getValue(context,String.class);}}完事啦!⼤家可以注意到关键⽅法就是parseKey/*** 获取缓存的key* key 定义在注解上,⽀持SPEL表达式* @return*/private String parseKey(String key, Method method, Object [] args){if(StringUtils.isEmpty(key)) return null;//获取被拦截⽅法参数名列表(使⽤Spring⽀持类库)LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paraNameArr = u.getParameterNames(method);//使⽤SPEL进⾏key的解析ExpressionParser parser = new SpelExpressionParser();//SPEL上下⽂StandardEvaluationContext context = new StandardEvaluationContext();//把⽅法参数放⼊SPEL上下⽂中for(int i=0;i<paraNameArr.length;i++){context.setVariable(paraNameArr[i], args[i]);}return parser.parseExpression(key).getValue(context,String.class);}⾃定义注解结合切⾯和spel表达式在我们的实际开发中可能存在这么⼀种情况,当⽅法参数中的某些条件成⽴的时候,需要执⾏⼀些逻辑处理,⽐如输出⽇志。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、各种注解方式1.@Autowired注解(不推荐使用,建议使用@Resource)@Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。

@Autowired的标注位置不同,它们都会在Spring在初始化这个bean时,自动装配这个属性。

要使@Autowired能够工作,还需要在配置文件中加入以下Xml代码1.<beanclass="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>2. @Qualifier注解@Autowired是根据类型进行自动装配的。

例如,如果当Spring上下文中存在不止一个UserDao类型的bean时,就会抛出BeanCreationException异常;如果Spring上下文中不存在UserDao类型的bean,也会抛出BeanCreationException异常。

我们可以使用@Qualifier配合@Autowired来解决这些问题。

如下:1). 可能存在多个UserDao实例Java代码1.@Autowired2.@Qualifier("userServiceImpl")3.public IUserService userService;或者Java代码1.@Autowired2.public void setUserDao(@Qualifier("userDao") UserDao userDao) {erDao = userDao;4.}这样,Spring会找到id为userServiceImpl和userDao的bean进行装配。

2). 可能不存在UserDao实例Java代码1.@Autowired(required = false)2.public IUserService userService;3. @Resource注解JSR-250标准注解,推荐使用它来代替Spring专有的@Autowired注解。

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按byName 自动注入罢了。

@Resource有两个属性是比较重要的,分别是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。

所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。

如果既不指定name也不指定type属性,这时将通过反射机制使用byName 自动注入策略。

要使@Autowired能够工作,还需要在配置文件中加入以下: Xml代码1.<beanclass="monAnnotationBeanPostProcessor"/>@Resource装配顺序:a.如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常b.如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常c.如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常d.如果既没有指定name,又没有指定type,则自动按照byName方式进行装配(见2);如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配;4. @PostConstruct(JSR-250)注解在方法上加上注解@PostConstruct,这个方法就会在Bean初始化之后被Spring容器执行(注:Bean初始化包括,实例化Bean,并装配Bean的属性(依赖注入))。

它的一个典型的应用场景是,当你需要往Bean里注入一个其父类中定义的属性,而你又无法复写父类的属性或属性的setter方法时,如:Java代码1.public class UserDaoImpl extends HibernateDaoSupport implements UserDao{2.3.private SessionFactory mySessionFacotry;4.5.@Resource6.public void setMySessionFacotry(SessionFactory sessionFacotry)7. {8.this.mySessionFacotry = sessionFacotry;9. }10.11.@PostConstruct12.public void injectSessionFactory()13. {14.super.setSessionFactory(mySessionFacotry);15. }16.}这里通过@PostConstruct,为UserDaoImpl的父类里定义的一个sessionFactory私有属性,注入了我们自己定义的 sessionFactory(父类的setSessionFactory方法为final,不可复写),之后我们就可以通过调用 super.getSessionFactory()来访问该属性了。

5. @PreDestroy(JSR-250)注解在方法上加上注解@PreDestroy,这个方法就会在Bean初始化之后被Spring容器执行。

其用法同@PostConstruct。

和@PostConstruct 区别在于:@PostConstruct注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。

6. @Component注解 (不推荐使用)只需要在对应的类上加上一个@Component注解,就将该类定义为一个Bean了。

Spring 还提供了更加细化的注解形式:@Repository、@Service、@Controller,它们分别对应存储层Bean,业务层Bean,和展示层Bean。

目前版本(2.5)中,这些注解与@Component的语义是一样的,完全通用,在Spring以后的版本中可能会给它们追加更多的语义。

所以,我们推荐使用@Repository、@Service、@Controller来替代@Component。

7.@Scope注解在使用XML定义Bean时,我们可能还需要通过bean的scope属性来定义一个Bean的作用范围,我们同样可以通过@Scope注解来完成这项工作:Java代码1.@Scope("session")2.@Component()3.public class UserSessionBean implements Serializable{4. ... ...5.}二、配置启用注解(注意以下配置需要使用spring2.5的头文件,在spring3.0中不适用)1.使用简化配置Spring2.1添加了一个新的context的Schema命名空间,该命名空间对注释驱动、属性文件引入、加载期织入等功能提供了便捷的配置。

我们知道注释本身是不会做任何事情的,它仅提供元数据信息。

要使元数据信息真正起作用,必须让负责处理这些元数据的处理器工作起来。

AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor就是处理这些注释元数据的处理器。

但是直接在Spring配置文件中定义这些Bean显得比较笨拙。

Spring为我们提供了一种方便的注册这些BeanPostProcessor的方式,这就是,以下是spring的配置。

Xml代码1.<beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"2.xsi:schemaLocation="/schema/beans3. /schema/beans/spring-beans-2.5.xsd4. /schema/context5./schema/context/spring-context-2.5.xsd">6.<context:annotation-config/>7.beans>将隐式地向Spring容器注册了AutowiredAnnotationBeanPostProcessor 、CommonAnnotationBeanPostProcessor 、PersistenceAnnotationBeanPostProcessorRequiredAnnotationBeanPostProcessor这4个BeanPostProcessor。

2.使用让Bean定义注解工作起来Xml代码1.<beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"2.xsi:schemaLocation="/schema/beans3. /schema/beans/spring-beans-2.5.xsd4. /schema/context5./schema/context/spring-context-2.5.xsd">6.<context:component-scan base-package="com.kedacom.ksoa"/>7.beans>这里,所有通过元素定义Bean的配置内容已经被移除,仅需要添加一行配置就解决所有问题了——Spring XML配置文件得到了极致的简化(当然配置元数据还是需要的,只不过以注释形式存在罢了)。

的base-package属性指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。

还允许定义过滤器将基包下的某些类纳入或排除。

Spring支持以下4种类型的过滤方式:过滤器类型 | 表达式范例 | 说明注解 | org.example.SomeAnnotation | 将所有使用SomeAnnotation注解的类过滤出来类名指定 | org.example.SomeClass | 过滤指定的类正则表达式 | com\.kedacom\.spring\.annotation\.web\..* | 通过正则表达式过滤一些类AspectJ表达式 | org.example..*Service+ | 通过AspectJ表达式过滤一些类以正则表达式为例,我列举一个应用实例:Xml代码1.<context:component-scan base-package="com.casheen.spring.annotation">2.<context:exclude-filter type="regex"expression="com\.casheen\.spring\.annotation\.web\..*"/>3.context:component-scan>值得注意的是配置项不但启用了对类包进行扫描以实施注释驱动Bean定义的功能,同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor),因此当使用后,就可以将移除了。

相关文档
最新文档